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

Author Topic: Shader not working when drawing VertexArray?  (Read 5804 times)

0 Members and 1 Guest are viewing this topic.

TheComet

  • Newbie
  • *
  • Posts: 12
    • View Profile
Shader not working when drawing VertexArray?
« on: May 31, 2013, 03:36:04 pm »
Hi,

I'm trying to render a fractal using a shader, and all I get is a black screen when I render the VertexArray.

I created a quad which covers the entire screen:

        // set up vertex array
        this->m_pQuad = new sf::VertexArray( sf::Quads, 4 );
        (*this->m_pQuad)[0].position = sf::Vector2f( 0, 0 );
        (*this->m_pQuad)[1].position = sf::Vector2f( static_cast<float>(window->getSize().x), 0.0 );
        (*this->m_pQuad)[2].position = sf::Vector2f( static_cast<float>(window->getSize().x), static_cast<float>(window->getSize().y) );
        (*this->m_pQuad)[3].position = sf::Vector2f( 0.0, static_cast<float>(window->getSize().y) );

And in my render routine, I do the following:

        // set shader uniforms
        this->m_pShader->setParameter( "maxX", maxX );
        this->m_pShader->setParameter( "maxY", maxY );
        this->m_pShader->setParameter( "minX", minX );
        this->m_pShader->setParameter( "minY", minY );
        this->m_pShader->setParameter( "maxIterations", maxIterations );

        // render to window
        window->draw( *this->m_pQuad, this->m_pShader );

The quad draws to the window if I change the last line to this:

        // render to window
        window->draw( *this->m_pQuad );

The vertex shader looks like this:

void main()
{
    // transform the vertex position
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

    // transform the texture coordinates
    gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;

    // forward the vertex color
    gl_FrontColor = gl_Color;
}

The fragment shader looks like this:

void main( void )
{
        vec4 colour = vec4(0.4f, 0.8f 0.1f, 0.0);
        gl_FragColor = colour;
}

Here is the entire class:

cFractalFrame.hpp
// -------------------------------------------------------------------
// Handles drawing of the fractal
// -------------------------------------------------------------------

#ifndef _CFRACTALFRAME_HPP_
#define _CFRACTALFRAME_HPP_

// -------------------------------------------------------------------
// include files
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>

namespace GPUFractalZoomer {

class cFractalFrame
{
public:

        // factal types
        enum FractalType
        {
                Mandelbrot
        };

        // constructor, destructor
        cFractalFrame( sf::RenderWindow* window );
        ~cFractalFrame( void );

        // load a fractal
        void load( FractalType type );

        // render fractal to window
        void render( sf::RenderWindow* window );

private:

        // use a quad to render the fractal
        sf::VertexArray* m_pQuad;

        // fragment program of the current fractal
        sf::Shader* m_pShader;

        // fractal parameters to be passed to the shader
        float minX;
        float maxX;
        float minY;
        float maxY;
        float maxIterations;
};

} // namespace GPUFractalZoomer

#endif // _CFRACTALFRAME_HPP_

cFractalFrame.cpp
// -------------------------------------------------------------------
// Handles drawing of the fractal
// -------------------------------------------------------------------

// -------------------------------------------------------------------
// include files
#include <cFractalFrame.hpp>
#include <cException.hpp>
#include <iostream>

namespace GPUFractalZoomer {

// -------------------------------------------------------------------
// constructor
cFractalFrame::cFractalFrame( sf::RenderWindow* window ) :
        m_pQuad( NULL ),
        m_pShader( NULL )
{
        // debug
        std::cout << "constructed cFractalFrame" << std::endl;

        // set up vertex array
        this->m_pQuad = new sf::VertexArray( sf::Quads, 4 );
        (*this->m_pQuad)[0].position = sf::Vector2f( 0, 0 );
        (*this->m_pQuad)[1].position = sf::Vector2f( static_cast<float>(window->getSize().x), 0.0 );
        (*this->m_pQuad)[2].position = sf::Vector2f( static_cast<float>(window->getSize().x), static_cast<float>(window->getSize().y) );
        (*this->m_pQuad)[3].position = sf::Vector2f( 0.0, static_cast<float>(window->getSize().y) );

        // create shader
        this->m_pShader = new sf::Shader();
}

// -------------------------------------------------------------------
// destructor
cFractalFrame::~cFractalFrame( void )
{
        // debug
        std::cout << "destructed cFractalFrame" << std::endl;

        delete this->m_pShader;
        delete this->m_pQuad;
}

// -------------------------------------------------------------------
// load a fractal
void cFractalFrame::load( FractalType type )
{
        switch( type )
        {

                // mandelbrot
                case Mandelbrot :

                        // attempt to load shader
                        if( !this->m_pShader->loadFromFile( "media/shaders/commonVertexShader.vsh", "media/shaders/simpletest.fsh" ) )
                        {
                                throw cException();
                        }

                        // set default zoom values
                        minX = -2.0f;
                        maxX = 1.0f;
                        minY = -1.2f;
                        maxY = 1.2f;
                        maxIterations = 10.0;

                        break;

                default :
                        break;
        }
}

// -------------------------------------------------------------------
// render fractal to window
void cFractalFrame::render( sf::RenderWindow* window )
{

        // set shader uniforms
        this->m_pShader->setParameter( "maxX", maxX );
        this->m_pShader->setParameter( "maxY", maxY );
        this->m_pShader->setParameter( "minX", minX );
        this->m_pShader->setParameter( "minY", minY );
        this->m_pShader->setParameter( "maxIterations", maxIterations );

        // render to window
        window->draw( *this->m_pQuad, this->m_pShader );
}

} // namespace GPUFractalZoomer

Where did I go wrong?
« Last Edit: May 31, 2013, 03:38:34 pm by TheComet »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Shader not working when drawing VertexArray?
« Reply #1 on: May 31, 2013, 03:52:08 pm »
Your fragment shader contains a syntax error (missing "," between two numbers).
Laurent Gomila - SFML developer

TheComet

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Shader not working when drawing VertexArray?
« Reply #2 on: May 31, 2013, 04:09:24 pm »
Fixed. :)

However, the problem still persists: I just get a black screen. My rendering routine looks like this now:

// -------------------------------------------------------------------
// render fractal to window
void cFractalFrame::render( sf::RenderWindow* window )
{

        // set shader uniforms
        /*
        this->m_pShader->setParameter( "maxX", maxX );
        this->m_pShader->setParameter( "maxY", maxY );
        this->m_pShader->setParameter( "minX", minX );
        this->m_pShader->setParameter( "minY", minY );
        this->m_pShader->setParameter( "maxIterations", maxIterations );*/


        // render to window
        window->draw( *this->m_pQuad, this->m_pShader );
}

The quad renders if I change the last line to this:

        // render to window
        window->draw( *this->m_pQuad );

It's very strange. I'm going to assume I'm doing something wrong in the vertex shader, but I can't see what.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Shader not working when drawing VertexArray?
« Reply #3 on: May 31, 2013, 04:15:56 pm »
What I don't understand is that your code didn't throw a cException before you fixed the syntax error in the shader.

Is there any message in the standard error output (console)?
Laurent Gomila - SFML developer

TheComet

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Shader not working when drawing VertexArray?
« Reply #4 on: May 31, 2013, 04:31:56 pm »
That was just my foolish editing of the shader in the last minute while I was writing that forum post. :P

The exception isn't being thrown now, I double checked. The shaders appear to compile and link successfully.

Could it have something to do with not setting the shader's "current texture"?


Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Shader not working when drawing VertexArray?
« Reply #5 on: May 31, 2013, 04:41:29 pm »
Is the black color outputed by the shader, or is it the window's clear color?

Quote
Could it have something to do with not setting the shader's "current texture"?
No.
Laurent Gomila - SFML developer

TheComet

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Shader not working when drawing VertexArray?
« Reply #6 on: May 31, 2013, 04:42:22 pm »
Quote
Is the black color outputed by the shader, or is it the window's clear color?

It's the window's clear colour.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Shader not working when drawing VertexArray?
« Reply #7 on: May 31, 2013, 04:51:07 pm »
Could you write a complete and minimal example that reproduces this problem (and only this problem, I don't care about your initial project), so that I can test it?

And please, put the shaders directly in the code (in string literals), everytime I ask for a minimal code about shaders I end up with separate files to load, which is really not convenient ;)
Laurent Gomila - SFML developer

TheComet

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Shader not working when drawing VertexArray?
« Reply #8 on: May 31, 2013, 05:14:58 pm »
Sure, here you go:

#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>

// -------------------------------------------------------------------
// Main entry point
int main( int argc, char* argv[] )
{

        // setup stuff
        sf::RenderWindow window( sf::VideoMode( 800, 600 ), "GPU Fractal Zoomer", sf::Style::Close | sf::Style::Titlebar );
        sf::Event event;

        // vertex shader
        const std::string vertexShader = \
                "void main()\n"\
                "{\n"\
                        "// transform the vertex position\n"\
                        "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"\
                        "\n"\
                        "// transform the texture coordinates\n"\
                        "gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"\
                        "\n"\
                        "// forward the vertex color\n"\
                        "gl_FrontColor = gl_Color;\n"\
                "}\n";

        // fragment shader
        const std::string fragmentShader = \
                "void main( void )\n"\
                "{\n"\
                        "vec4 colour = vec4(0.4f, 0.8f, 0.1f, 0.0);\n"\
                        "gl_FragColor = colour;\n"\
                "}\n";

        // load shader
        sf::Shader shader;
        shader.loadFromMemory( vertexShader, fragmentShader );

        // create quad
        sf::VertexArray quad( sf::Quads, 4 );
        quad[0].position = sf::Vector2f( 0, 0 );
        quad[1].position = sf::Vector2f( static_cast<float>(window.getSize().x), 0.0 );
        quad[2].position = sf::Vector2f( static_cast<float>(window.getSize().x), static_cast<float>(window.getSize().y) );
        quad[3].position = sf::Vector2f( 0.0, static_cast<float>(window.getSize().y) );

        // main loop
        while( window.isOpen() )
        {

                // render
                window.clear( sf::Color::Black );
                window.draw( quad, &shader );
                window.display();

                // poll window events
                while( window.pollEvent( event ) )
                {
                        switch( event.type )
                        {

                                // close window was requested
                                case sf::Event::Closed :
                                        window.close();
                                        break;

                                // not interested in this event
                                default :
                                        break;

                        }
                }

        }

        return 0;
}

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Shader not working when drawing VertexArray?
« Reply #9 on: May 31, 2013, 07:19:15 pm »
Perfect, thank you very much :)

However I found the error while pasting the code in my IDE, I didn't even test it ;D

Your fragment shader outputs a pixel with alpha = 0 (transparent). Use alpha > 0 if you want to see something.
Laurent Gomila - SFML developer

TheComet

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Shader not working when drawing VertexArray?
« Reply #10 on: May 31, 2013, 07:59:06 pm »
Doh, I literally facepalmed when I read that.  ;D

Just one more problem left now. In the fragment program, gl_TexCoord[0] doesn't seem to ever change, i.e. it isn't returning the coordinates of the current pixel, but it's always zero.

What could be causing this?

Vertex:
void main( void )
{
        vec4 colour = vec4(gl_TexCoord[0].xy, 0.4f, 1.0);
        gl_FragColor = colour;
}

Fragment:
void main()
{
    // transform the vertex position
    gl_Position = ftransform();

    // transform the texture coordinates
    gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;

    // forward the vertex color
    gl_FrontColor = gl_Color;
}

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Shader not working when drawing VertexArray?
« Reply #11 on: May 31, 2013, 08:16:20 pm »
You didn't set texCoords of the vertices in your 'sf::VertexArray quad' so they default to 0.f,0.f.
Back to C++ gamedev with SFML in May 2023

TheComet

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Shader not working when drawing VertexArray?
« Reply #12 on: May 31, 2013, 08:37:05 pm »
Perfect, thanks a lot for all of the help!