【问题标题】:Simple 2D matrix rotation in OpenGL with GLSL produces no output使用 GLSL 的 OpenGL 中的简单 2D 矩阵旋转不产生输出
【发布时间】:2018-03-25 23:39:40
【问题描述】:

我开始学习 OpenGL 并做一些早期示例来了解 API 如何使用它。我目前坚持的,是一个旋转的例子。代码(在下面提供)应该从 4 个顶点创建一个 2D 正方形,并围绕 Z 轴应用 30º 的旋转。显然,代码看起来很好,我已经看到它在我教授的机器上运行并且它可以工作。如果我绘制正方形而不在着色器中应用旋转,程序当然会绘制正方形,但不旋转。

这可能是由一些错误的配置引起的吗?所有其他示例似乎都可以正常工作。

代码如下:

#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;
}

Angel.h 是一个附加资源,有助于对所有这些库进行一些管理。可以找到hereInitShader 的实现是here

顶点着色器:

#version 130

in vec4 vPosition;
uniform mat4 rot;

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

如果我不乘rot * vPosition,则绘制“未旋转”的正方形

碎片着色器:

#version 130

out vec4 fColor;

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

【问题讨论】:

  • 这有什么关系?它可能会以错误的角度旋转,而不是 30 度。但是 OP 说他没有看到任何轮换。
  • 静态方法是glm::degress(30.0f) rigth?我试过这种方式,但仍然是一个空白窗口
  • 您需要为此升级显卡驱动程序。新的显卡驱动程序将与新版本的 OpenGL 和 GLSL 一起提供。
  • @ParitoshKulkarni 我有版本 0.9.9-a1 并尝试了两种方式(glm::degress(30.0f)30.0f,但效果不佳
  • 我认为只是更新驱动程序也更改为双缓冲替换 glutInitDisplayMode( GLUT_SINGLE | GLUT_RGBA );到 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);

标签: c++ opengl rotation glsl glut


【解决方案1】:

使用 FreeGLUT、GLUT_DOUBLE 和 GLM 0.9.8.4 在我的机器上运行良好:


#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;
}

【讨论】:

  • 即使你的代码不工作,我的图形驱动程序一定是过时的。我尝试升级它们
  • @LucasHenrique:你得到的是白色背景色并且没有正方形吗?还是其他一些故障模式?
  • 只有白色背景
  • @LucasHenrique:在您的调试器中(或通过printf()/cout)检查locmatRot 的值,它们应该是非负数。
  • @LucasHenrique:您也可以尝试注释掉 VAO 创建/绑定。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-19
  • 1970-01-01
  • 1970-01-01
  • 2013-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多