Lucas Henrique
Lucas Henrique

Reputation: 187

Simple 2D matrix rotation in OpenGL with GLSL produces no output

I'm starting to learn about OpenGL and doing some early examples to understand the API how to use it. The I'm currently stuck on, is with a rotation example. The code, (provided bellow) is supposed to create a 2D square from 4 vertices and apply a rotation of 30º around the Z axis. Apparently, the code seems fine and I've seen it running in my professor's machine and it works. If I draw the square without applying the rotation inside the shader, the program draws the square, but with no rotation, of course.

Could this be caused by some bad configuration? All the other examples seems to work fine.

Here is the code:

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "Angel.h"

glm::vec2 vertices[4] = {
    glm::vec2( -0.5, -0.5 ),
    glm::vec2(  0.5, -0.5 ),
    glm::vec2(  0.5,  0.5 ),
    glm::vec2( -0.5,  0.5 ),
};

const int NumPoints = 6;
glm::vec2 points[NumPoints];

void square( ){
    points[0] = vertices[0];
    points[1] = vertices[1];
    points[2] = vertices[2];
    points[3] = vertices[0];
    points[4] = vertices[2];
    points[5] = vertices[3];
}

GLuint matRot;
void init( void ){
    square();
    GLuint vao;
    glGenVertexArrays( 1, &vao );
    glBindVertexArray( vao );

    GLuint buffer;
    glGenBuffers( 1, &buffer );
    glBindBuffer( GL_ARRAY_BUFFER, buffer );
    glBufferData( GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW );

    GLuint program = InitShader( "vshader1.glsl", "fshader1.glsl" );
    glUseProgram( program );

    GLuint loc = glGetAttribLocation( program, "vPosition" );
    glEnableVertexAttribArray( loc );
    glVertexAttribPointer( loc, 2, GL_FLOAT, GL_FALSE, 0,
                           BUFFER_OFFSET(0) );

    matRot = glGetUniformLocation( program, "rot" );

    glClearColor( 1.0, 1.0, 1.0, 1.0 ); 
}

void display( void ){
    glClear( GL_COLOR_BUFFER_BIT );    

    glm::mat4 rotZ; 
    rotZ = glm::rotate(rotZ, glm::radians(30.0f), glm::vec3(0.0f,0.0f,1.0f));
    glUniformMatrix4fv(matRot,1,GL_FALSE, glm::value_ptr(rotZ)); 

    glDrawArrays( GL_TRIANGLES, 0, NumPoints );  
    glFlush();
}

int main( int argc, char **argv ){
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_SINGLE | GLUT_RGBA );
    glutInitWindowSize( 512, 512 );
    glutInitWindowPosition(0,0);
    glutCreateWindow( "square rotation" );

    glewInit(); 

    init();

    glutDisplayFunc( display );

    glutMainLoop();
    return 0;
}

The Angel.h is an additional resource that helps with some management of all those libraries. It can be found here and the InitShader implementation is here

The vertex shader:

#version 130

in vec4 vPosition;
uniform mat4 rot;

void main()
{
    gl_Position = rot * vPosition;
}

If I don't multiply rot * vPosition, the "un-rotated" square is drawn

And the fragments shadder:

#version 130

out vec4 fColor;

void main()
{
    fColor = vec4( 1.0, 0.0, 0.0, 1.0 );
}

Upvotes: 0

Views: 1443

Answers (1)

genpfault
genpfault

Reputation: 52157

Workin' fine on my machine with FreeGLUT, GLUT_DOUBLE, & GLM 0.9.8.4:

screenshot of rotated square

#include <GL/glew.h>
#include <GL/glut.h>
#include <iostream>
#include <cstdarg>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

struct Program
{
    static GLuint Load( const char* shader, ... )
    {
        GLuint prog = glCreateProgram();
        va_list args;
        va_start( args, shader );
        while( shader )
        {
            const GLenum type = va_arg( args, GLenum );
            AttachShader( prog, type, shader );
            shader = va_arg( args, const char* );
        }
        va_end( args );
        glLinkProgram( prog );
        CheckStatus( prog );
        return prog;
    }

private:
    static void CheckStatus( GLuint obj )
    {
        GLint status = GL_FALSE;
        if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
        if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
        if( status == GL_TRUE ) return;
        GLchar log[ 1 << 15 ] = { 0 };
        if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
        if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
        std::cerr << log << std::endl;
        exit( EXIT_FAILURE );
    }

    static void AttachShader( GLuint program, GLenum type, const char* src )
    {
        GLuint shader = glCreateShader( type );
        glShaderSource( shader, 1, &src, NULL );
        glCompileShader( shader );
        CheckStatus( shader );
        glAttachShader( program, shader );
        glDeleteShader( shader );
    }
};

#define GLSL(version, shader) "#version " #version "\n" #shader

glm::vec2 vertices[4] =
{
    glm::vec2( -0.5, -0.5 ),
    glm::vec2(  0.5, -0.5 ),
    glm::vec2(  0.5,  0.5 ),
    glm::vec2( -0.5,  0.5 ),
};

const int NumPoints = 6;
glm::vec2 points[NumPoints];

void square( )
{
    points[0] = vertices[0];
    points[1] = vertices[1];
    points[2] = vertices[2];
    points[3] = vertices[0];
    points[4] = vertices[2];
    points[5] = vertices[3];
}

GLuint matRot;
void init( void )
{
    square();
    GLuint vao;
    glGenVertexArrays( 1, &vao );
    glBindVertexArray( vao );

    GLuint buffer;
    glGenBuffers( 1, &buffer );
    glBindBuffer( GL_ARRAY_BUFFER, buffer );
    glBufferData( GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW );

    const char* vert = GLSL
    (
        130,
        in vec4 vPosition;
        uniform mat4 rot;

        void main()
        {
            gl_Position = rot * vPosition;
        }
    );

    const char* frag = GLSL
    (
        130,
        out vec4 fColor;

        void main()
        {
            fColor = vec4( 1.0, 0.0, 0.0, 1.0 );
        }
    );
    GLuint program = Program::Load( vert, GL_VERTEX_SHADER, frag, GL_FRAGMENT_SHADER, NULL );
    glUseProgram( program );

    GLuint loc = glGetAttribLocation( program, "vPosition" );
    glEnableVertexAttribArray( loc );
    glVertexAttribPointer( loc, 2, GL_FLOAT, GL_FALSE, 0, (void*)0 );

    matRot = glGetUniformLocation( program, "rot" );

    glClearColor( 1.0, 1.0, 1.0, 1.0 ); 
}


void display()
{
    glClear( GL_COLOR_BUFFER_BIT );    

    glm::mat4 rotZ; 
    rotZ = glm::rotate(rotZ, glm::radians(30.0f), glm::vec3(0.0f,0.0f,1.0f));
    glUniformMatrix4fv(matRot,1,GL_FALSE, glm::value_ptr(rotZ)); 

    glDrawArrays( GL_TRIANGLES, 0, NumPoints );  

    glutSwapBuffers();
}

int main(int argc, char **argv)
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
    glutInitWindowSize( 600, 600 );
    glutCreateWindow( "GLUT" );

    glewExperimental = GL_TRUE;
    glewInit();

    init();

    glutDisplayFunc( display );
    glutMainLoop();
    return 0;
}

Upvotes: 2

Related Questions