glUseProgram影响的不仅仅是VAO

时间:2014-01-24 16:08:13

标签: c++ opengl

我已经成功创建了一个VAO,它可以生成一个三角形,然后可以用鼠标旋转(在着色器的帮助下)。

当我尝试使用标准的'glBegin()'和'glEnd()'函数绘制其他东西时,我的问题出现了。它成功绘制,但现在,当我尝试旋转三角形时,新绘图也会旋转。

我知道问题以某种方式使用glUseProgram()函数修复,但我不完全确定应该添加的原因或位置。

这是我的代码(我已经添加了所有内容,但焦点的主要区域应该是display()和init()函数:

#include <GL/glew/glew.h>
#include <GL/freeglut.h>
#include <CoreStructures\CoreStructures.h>
#include <iostream>
#include "texture_loader.h"
#include "shader_setup.h"


using namespace std;
using namespace CoreStructures;


float theta = 0.0f;

bool mDown = false;
int mouse_x, mouse_y;


GLuint myShaderProgram;

GLuint locT; // location of "T" uniform variable in myShaderProgram
GLuint locR; // location of "R" uniform variable in myShaderProgram

GLuint sunPosVBO, sunColourVBO, sunIndicesVBO, sunVAO;

// Packed vertex arrays for the star object

// 1) Position Array - Store vertices as (x,y) pairs
static GLfloat sunVertices [] = {

    -0.1f, 0.7f,
    0.1f, 0.7f,
    0.0f, 0.55f
};

// 2) Colour Array - Store RGB values as unsigned bytes
static GLubyte sunColors [] = {

    255, 0, 0, 255,
    255, 255, 0, 255,
    0, 255, 0, 255
};

// 4) Index Array - Store indices to star vertices - this determines the order the vertices are to be processed
static GLubyte sunVertexIndices [] = {0, 1, 2};



void setupSunVAO(void) {

    glGenVertexArrays(1, &sunVAO);
    glBindVertexArray(sunVAO);

    // copy star vertex position data to VBO
    glGenBuffers(1, &sunPosVBO);
    glBindBuffer(GL_ARRAY_BUFFER, sunPosVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(sunVertices), sunVertices, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)0);

    // copy star vertex colour data to VBO
    glGenBuffers(1, &sunColourVBO);
    glBindBuffer(GL_ARRAY_BUFFER, sunColourVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(sunColors), sunColors, GL_STATIC_DRAW);
    glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, (const GLvoid*)0);

    // enable position, colour buffer inputs
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    // setup star vertex index array
    glGenBuffers(1, &sunIndicesVBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sunIndicesVBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(sunVertexIndices), sunVertexIndices, GL_STATIC_DRAW);


    glBindVertexArray(0);
}


void report_version(void) {

    int majorVersion, minorVersion;

    glGetIntegerv(GL_MAJOR_VERSION, &majorVersion);
    glGetIntegerv(GL_MINOR_VERSION, &minorVersion);

    cout << "OpenGL version " << majorVersion << "." << minorVersion << "\n\n";
}


void init(void) {

    // initialise glew library
    GLenum err = glewInit();

    // ensure glew was initialised successfully before proceeding
    if (err==GLEW_OK)
        cout << "GLEW initialised okay\n";
    else
        cout << "GLEW could not be initialised\n";

    report_version();

    glClearColor(0.0, 0.0, 0.0, 0.0);


    //
    // setup "sun" VBO and VAO object
    //
    setupSunVAO();


    //
    // load shader program
    //
    myShaderProgram = setupShaders(string("Resources\\Shaders\\basic_vertex_shader.txt"), string("Resources\\Shaders\\basic_fragment_shader.txt"));

    // get the index / location of the uniform variables "T" and "R" in shader program "myShaderProgram"
    locT = glGetUniformLocation(myShaderProgram, "T");
    locR = glGetUniformLocation(myShaderProgram, "R");

    // "plug-in" shader into GPU pipeline
    glUseProgram(myShaderProgram); // we're in the driving seat!!!!!  Our shaders now intercept and process our vertices as part of the GPU rendering pipeline (as shown in the lecture notes)
}


// Example rendering functions - draw objects in local, or modelling coordinates

void drawSun(void) {

    glBindVertexArray(sunVAO);
    glDrawElements(GL_TRIANGLE_STRIP, 3, GL_UNSIGNED_BYTE, (GLvoid*)0);
}


void drawShape()
{
    glColor3f(0.0f, 0.6f, 0.2f);
    glBegin(GL_POLYGON);

    glVertex2f(-1.0f, -1.0f);   //  Left
    glVertex2f(-1.0f, -0.1f);


    glVertex2f(-0.9f, -0.05f);
    glVertex2f(-0.55f, -0.045f);
    glVertex2f(-0.49f, -0.06f);
    glVertex2f(-0.4f, -0.055f);
    glVertex2f(-0.2f, -0.052f);

    glVertex2f(0.0f, -0.02f);   //  Middle

    glVertex2f(0.3f, -0.085f);
    glVertex2f(0.5f, -0.08f);
    glVertex2f(0.8f, -0.088f);

    glVertex2f(1.0f, -0.1f);
    glVertex2f(1.0f, -1.0f);    //  Right

    glEnd();
}

//
//
void drawScene()
{
    drawSun();

    drawShape();
}

void display(void) {

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Setup translation matrix and store in T.  Pass this over the the shader with the function glUniformMatrix4fv
    GUMatrix4 T = GUMatrix4::translationMatrix(0.01f, 0.01f, 0.0f);
    glUniformMatrix4fv(locT, 1, GL_FALSE, (GLfloat*)&T);

    // Setup rotation matrix and store in R.  Pass this over the the shader with the function glUniformMatrix4fv
    GUMatrix4 R = GUMatrix4::rotationMatrix(0.0f, 0.0f, theta);
    glUniformMatrix4fv(locR, 1, GL_FALSE, (GLfloat*)&R);

    // Draw the scene (the above transformations will be applied to each vertex in the vertex shader)
    drawScene();

    glutSwapBuffers();
}


void mouseButtonDown(int button_id, int state, int x, int y) {

    if (button_id==GLUT_LEFT_BUTTON) {

        if (state==GLUT_DOWN) {

            mouse_x = x;
            mouse_y = y;

            mDown = true;

        } else if (state == GLUT_UP) {

            mDown = false;
        }
    }
}


void mouseMove(int x, int y) {

    if (mDown) {

        int dx = x - mouse_x;
        int dy = y - mouse_y;

        float delta_theta = (float)dy * (3.142f * 0.01f);
        theta += delta_theta;

        mouse_x = x;
        mouse_y = y;

        glutPostRedisplay();
    }
}



void keyDown(unsigned char key, int x, int y) {

    if (key=='r') {

        theta = 0.0f;
        glutPostRedisplay();
    }
}


int main(int argc, char **argv) {

    glutInit(&argc, argv);
    initCOM();

    glutInitContextVersion(3, 3);
    glutInitContextProfile (GLUT_COMPATIBILITY_PROFILE);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);

    glutInitWindowSize(800, 800);
    glutInitWindowPosition(0, 0);
    glutCreateWindow("Combining Transforms");

    glutDisplayFunc(display);
    glutKeyboardFunc(keyDown);
    glutMouseFunc(mouseButtonDown);
    glutMotionFunc(mouseMove);

    init();

    glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
    glutMainLoop();

    shutdownCOM();

    return 0;
}

修改 的 我有一个x,y顶点数组,我试图将它们与上面的代码一起绘制。出于某种原因,这似乎从sunVAO获取顶点数据。

是否需要清除某种缓存?我搜索过谷歌,但我似乎无法找到其他有VAO和顶点阵列冲突的人。

(另外,我检查了我的代码,并且顶点数组中提供的顶点数据是正确的,它们只是没有正确显示。)

代码:

static GLfloat bottomMarkerVertices[] = {
    -0.045f, -0.75f,
    0.045f, -0.75f,
    -0.07f, -1.0f,
    0.07f, -1.0f
};

glVertexPointer(2, GL_FLOAT, 0, bottomMarkerVertices);

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

注意:已启用顶点数组。

2 个答案:

答案 0 :(得分:0)

场景的两个元素一起移动,因为它们都使用相同的转换矩阵,具体如下:

// Setup translation matrix and store in T.  Pass this over the the shader with the   function glUniformMatrix4fv
GUMatrix4 T = GUMatrix4::translationMatrix(0.01f, 0.01f, 0.0f);
glUniformMatrix4fv(locT, 1, GL_FALSE, (GLfloat*)&T);

// Setup rotation matrix and store in R.  Pass this over the the shader with the function glUniformMatrix4fv
GUMatrix4 R = GUMatrix4::rotationMatrix(0.0f, 0.0f, theta);
glUniformMatrix4fv(locR, 1, GL_FALSE, (GLfloat*)&R);

如果您希望drawShape()不能随鼠标移动,则需要在调用之前重置locR theta值。

drawSun();

GUMatrix4 R = GUMatrix4::rotationMatrix(0.0f, 0.0f, 0.0f);
glUniformMatrix4fv(locR, 1, GL_FALSE, (GLfloat*)&R);

drawShape();

答案 1 :(得分:0)

假设您在标准化设备空间中定义坐标(由明显缺少投影矩阵表示),渲染循环需要看起来像这样:

void drawScene()
{
    //update shader parameters for the sun shader if necessary
    drawSun();

    glUseProgram(0);
    // at this point, the PROJECTION and MODELVIEW matrices are both the identity
    // so the shape is expected to be in NDCs and is not to be transformed
    // at all
    drawShape();                      
    glUseProgram(progForSun);
}

请注意,我不建议将旧版和现代版OpenGL混合使用。 drawShape()触发的顶点处理结果仅定义,因为您使用的是兼容性配置文件上下文