【问题标题】:Why this code does not display nothing on screen [closed]为什么此代码在屏幕上不显示任何内容[关闭]
【发布时间】:2018-03-13 04:09:05
【问题描述】:

我已经学习了几个教程,但我不明白为什么这段代码没有显示任何内容。

请注意,LoadShaders 效果很好。

我已经复制并粘贴了,所以我认为问题不是来自它......

#include <iostream>
#include <fstream>
#include <vector>  
#include <GL/glew.h>
#include <GL/gl.h>      
#include <GLFW/glfw3.h>

GLFWwindow* window;

int main(int argc, const char * argv[])
{
    if( !glfwInit() )
    {
        return -1;
    }
    glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // We want OpenGL 3.3
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);

    window = glfwCreateWindow(640, 480, "Test1", NULL, NULL);
    if( window == NULL )
    {
        return -1;
    }
    glfwMakeContextCurrent(window);

    glewExperimental = true; // Needed for core profile
    if (glewInit() != GLEW_OK)
    {
        return -1;
    }

    GLuint programID = LoadShaders( "SimpleVertexShader.vertexshader", "SimpleFragmentShader.fragmentshader" );

    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
    glClearColor(0.0f, 1.0f, 1.0f, 1.0f);

    do
    {
        glfwPollEvents();

        glUseProgram(programID);
        float vertices[] = {-0.5, -0.5,   0.0, 0.5,   0.5, -0.5};
        glClear(GL_COLOR_BUFFER_BIT);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
        glEnableVertexAttribArray(0);
        glDrawArrays(GL_TRIANGLES, 0, 3);
        glDisableVertexAttribArray(0);

        glfwSwapBuffers(window);
    }
    while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && glfwWindowShouldClose(window) == 0 );

    glfwTerminate();

    return 0;
}

感谢您的帮助

注意:

这里是 SimpleFragmentShader.fragmentshader:

#version 330 core
out vec3 color;
void main()
{
    color = vec3(1,0,0);
}

这里是 SimpleVertexShader.vertexshader:

#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
void main()
{
    gl_Position.xyz = vertexPosition_modelspace;
    gl_Position.w = 1.0;
}

请注意,我也尝试过像这样处理 3D 坐标:

float vertices[] = {-0.5, -0.5,0.0,   0.0, 0.5,0.0,   0.5, -0.5,0.0};

glClear(GL_COLOR_BUFFER_BIT);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);

【问题讨论】:

  • 如果它 not 显示 nothing,那么一切都很好,不是吗? ;-)(这是一个厚颜无耻的暗示,你的问题标题中有一个不应该出现的双重否定)
  • 我应该看到一个三角形
  • glGetError() 能告诉你什么吗?您采取了哪些调试步骤?
  • 转到使用 VBO 和 VAO 的教程

标签: opengl


【解决方案1】:

见docs.GL - OpenGL 3.3 - glVertexAttribPointer:

GL_INVALID_OPERATION 如果没有绑定顶点数组对象,则在核心上下文中生成。

您必须创建Vertex Array Object 和Vertex Buffer Object。

生成(glGenVertexArrays)并绑定(glBindVertexArray)Vertex Array Object:

GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );

生成 (glGenBuffers) 并绑定 (glBindBuffer) Vertex Buffer Object:

GLuint vbo;
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );

绑定缓冲区数据(glBufferData),启用顶点属性并定义通用顶点属性数据数组:

float vertices[] = {-0.5, -0.5,   0.0, 0.5,   0.5, -0.5};
glBufferData( GL_ARRAY_BUFFER, 6 * sizeof( float ), vertices, GL_STATIC_DRAW );
glEnableVertexAttribArray( 0 );
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 0, nullptr );
glBindVertexArray( 0 );

绘制网格时,只需要绑定顶点数组对象即可:

glBindVertexArray( vao );
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray( 0 );


请注意,由于您在片段着色器中使用用户定义的out 变量,因此您应该将片段数据位置与glBindFragDataLocation 绑定。请注意,这必须在片段着色器附加到着色器程序之后,但在着色器程序被链接之前完成。

【讨论】:

  • 只有在启用核心上下文的情况下。如果使用兼容性,他的代码是有效的。
  • @robthebloke 是的,答案“如果没有绑定顶点数组对象,则在核心上下文中生成 GL_INVALID_OPERATION”中提到了这一点。并且在“我们想要 OpenGL 3.3”问题的代码中被通缉。
  • 您必须使用 GLFW_OPENGL_PROFILE 选择加入核心配置文件
【解决方案2】:

您没有绑定输出片段数据位置:

GLuint programID = LoadShaders( "SimpleVertexShader.vertexshader", "SimpleFragmentShader.fragmentshader" );

// make sure you set which colour is the output from the fragment shader!
glBindFragDataLocation(programID, 0, "color");

(假设您在桌面上使用的是 OpenGL 3.3,而不是 OpenGL ES 3)


/edit 如果你想要一个 OpenGL 4.5 版本:

#include <iostream>
#include <fstream>
#include <vector>  
#include <GL/glew.h>
#include <GL/gl.h>      
#include <GLFW/glfw3.h>

GLFWwindow* window;

int main(int argc, const char * argv[])
{
  if( !glfwInit() )
  {
    return -1;
  }
  glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing
  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); 
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);

  window = glfwCreateWindow(640, 480, "Test1", NULL, NULL);
  if( window == NULL )
  {
    return -1;
  }
  glfwMakeContextCurrent(window);

  glewExperimental = true; // Needed for core profile
  if (glewInit() != GLEW_OK)
  {
    return -1;
  }
  glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);

  GLuint programID = LoadShaders( "SimpleVertexShader.vertexshader", "SimpleFragmentShader.fragmentshader" );

  // make sure you set which colour is the output from the fragment shader!
  glBindFragDataLocation(programID, 0, "color");

  glClearColor(0.0f, 1.0f, 1.0f, 1.0f);

  GLuint vbo = 0, vao = 0;
  const float vertices[] = {-0.5, -0.5,   0.0, 0.5,   0.5, -0.5};

  // create the vbo identifier
  glCreateBuffers(1, &vbo);

  // load the vertex data into the vertex buffer object (using immutable read only storage)
  glNamedBufferStorage(vbo, 6 * sizeof(float), vertices, 0);

  // create the vertex array object (vao)
  GLuint vao = 0;
  glCreateVertexArrays(1, &vao);

  // attach vbo to slot 0 on the vao
  glVertexArrayVertexBuffer(vao, 0, vbo, 0, sizeof(float) * 2);

  // fetch attribute 0 from the buffer bound to slot 0
  glVertexArrayAttribBinding(vao, 0, 0);

  // enable the vertex attribute 0
  glEnableVertexArrayAttrib(vao, 0);

  // specify the data type found in attribute 0
  glVertexArrayAttribFormat(vao, 0, 2, GL_FLOAT, false, 0);

  do
  {
    glfwPollEvents();

    // specify which program to use
    glUseProgram(programID);

    // specify which buffers to bind to the shader inputs
    glBindVertexArray(vao);

    // draw the data 
    glDrawArrays(GL_TRIANGLES, 0, 3);

    // done with the vao binding
    glBindVertexArray(0);    

    glfwSwapBuffers(window);
  }
  while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && glfwWindowShouldClose(window) == 0 );

  glfwTerminate();

  return 0;
}

【讨论】:

  • 如果您没有绑定输出片段颜色,屏幕上不会显示任何内容。假设 OP 正在使用兼容性配置文件,那么他发布的代码将起作用。
  • 鉴于如何拼写“颜色”之间存在分歧,总是绑定到“颜色”的代码将是一个非常糟糕的设计。 (而且我也向大学生教授 OpenGL 多年,所以你习惯于诊断相同的常见问题)
  • 它也可以是一个简单地返回零的函数,或者第一个参数可以是一个片段着色器。或者当前工作目录可能与 OP 所期望的不同。就你所知,着色器可能只附加到程序对象上。 (FWIW 虽然规范说您需要在链接之前调用 glBindFragDataLocation,但我不知道有任何 GPU 在链接失败后调用它)
猜你喜欢
  • 2013-07-06
  • 1970-01-01
  • 2016-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-22
  • 1970-01-01
相关资源
最近更新 更多