【问题标题】:glUseProgram affecting more than just the VAOglUseProgram 影响的不仅仅是 VAO
【发布时间】:2014-01-25 04:05:18
【问题描述】:

我已经成功创建了一个 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);

注意:顶点数组已启用。

【问题讨论】:

  • IMO,如果您已经关闭了 VAO,请不要使用立即模式渲染(glBegin 和朋友)。它们在 OpenGL 3 中已被贬低和删除,这是有充分理由的(它们非常低效)。
  • 首先,如果您已经在使用 VAO,为什么(对不起)您仍然使用即时模式?此外,如果您不希望通过顶点着色器转换内容,只需使用带有传递 VS 的程序即可。
  • 遗憾的是,我没有不混合它们的选项。
  • @AdamCarter:所以已经存在无法重构的代码?
  • @thokra 我可以更改代码,但我需要将即时渲染模式与 VAO 结合起来

标签: c++ opengl


【解决方案1】:

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

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() 触发的顶点处理结果仅在您使用兼容性配置文件上下文时被定义。

【讨论】:

  • 这正是我需要的!太感谢了。也谢谢你的解释:)
  • @AdamCarter:提醒一下,如果在你的大学里他们积极建议你编写这样的代码,你真的应该质疑这门课程。
【解决方案2】:

场景的两个元素一起移动,因为它们都使用相同的变换矩阵,由这些行指定:

// 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();

【讨论】:

  • 非常感谢!不过,我的一个着色器现在仍在影响 drawShape() 形状的颜色。我是否使用 glUseProgram(0) 来阻止这种情况发生?
  • @thokra 你能详细说明一下吗?哈哈。感谢您到目前为止的帮助
  • drawShape() 中将glUseProgram(0) 放在glColor3f() 之前?如果是这样,它会停止转换。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-12
  • 2020-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多