草庐IT

c++ - OpenGL:Radeon 驱动程序似乎与深度测试混淆

coder 2024-02-19 原文

我在深度测试方面遇到了一个非常奇怪的问题。 我在 Windows 上的 OpenGL 3.3 核心配置文件上下文中渲染一个简单的网格,启用深度测试并将 glDepthFunc 设置为 GL_LESS。在我的机器上(配备 nVidia Geforce GTX 660M 的笔记本电脑),一切都按预期工作,深度测试正常,这就是它的样子:

现在,如果我在另一台 PC 上运行该程序,一台配备 Radeon R9 280 的塔式电脑,它看起来更像这样:

奇怪的是,真正奇怪的是,当我在绘制前的每一帧调用 glEnable(GL_DEPTH_TEST) 时,结果在两台机器上都是正确的。 当我这样做时它正在工作,我认为在两台机器上都正确创建了深度缓冲区,当我在初始化时只启用一次深度测试时,它似乎在渲染之前以某种方式被禁用。 这是可能以某种方式成为问题的一部分的最少代码:

在创建上下文并使其成为当前上下文之后,在初始化时调用的代码:

glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);

在缓冲区交换之前调用每一帧的代码:

glClearColor(0.4f, 0.6f, 0.8f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// mShaderProgram->getID() simply returns the handle of a simple shader program
glUseProgram(mShaderProgram->getID());  

glm::vec3 myColor = glm::vec3(0.7f, 0.5f, 0.4f);
GLuint colorLocation = glGetUniformLocation(mShaderProgram->getID(), "uColor");
glUniform3fv(colorLocation, 1, glm::value_ptr(myColor));

glm::mat4 modelMatrix = glm::mat4(1.0f);
glm::mat4 viewMatrix = glm::lookAt(glm::vec3(0.0f, 3.0f, 5.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 projectionMatrix = glm::perspectiveFov(60.0f, (float)mWindow->getProperties().width, (float)mWindow->getProperties().height, 1.0f, 100.0f);
glm::mat4 inverseTransposeMVMatrix = glm::inverseTranspose(viewMatrix*modelMatrix);

GLuint mMatrixLocation = glGetUniformLocation(mShaderProgram->getID(), "uModelMatrix");
GLuint vMatrixLocation = glGetUniformLocation(mShaderProgram->getID(), "uViewMatrix");
GLuint pMatrixLocation = glGetUniformLocation(mShaderProgram->getID(), "uProjectionMatrix");
GLuint itmvMatrixLocation = glGetUniformLocation(mShaderProgram->getID(), "uInverseTransposeMVMatrix");

glUniformMatrix4fv(mMatrixLocation, 1, GL_FALSE, glm::value_ptr(modelMatrix));
glUniformMatrix4fv(vMatrixLocation, 1, GL_FALSE, glm::value_ptr(viewMatrix));
glUniformMatrix4fv(pMatrixLocation, 1, GL_FALSE, glm::value_ptr(projectionMatrix));
glUniformMatrix4fv(itmvMatrixLocation, 1, GL_FALSE, glm::value_ptr(inverseTransposeMVMatrix));

// Similiar to the shader program, mMesh.gl_vaoID is simply the handle of a vertex array object
glBindVertexArray(mMesh.gl_vaoID);

glDrawArrays(GL_TRIANGLES, 0, mMesh.faces.size()*3);

使用上面的代码,我会在 Radeon 上得到错误的输出。 注意:我使用 GLFW3 来创建上下文,使用 GLEW 来创建函数指针(显然还有 GLM 来进行数学计算)。 顶点数组对象包含三个属性数组缓冲区,用于位置、uv 坐标和法线。每一个都应该正确配置并发送到着色器,因为在每一帧启用深度测试时一切都工作正常。

我还应该提到,Radeon 机器运行的是 Windows 8,而 nVidia 机器运行的是 Windows 7。

编辑:根据要求,这是用于加载网格和创建属性数据的代码。我没有创建任何元素缓冲区对象,因为我没有使用元素绘制调用。

std::vector<glm::vec3> positionData;
std::vector<glm::vec2> uvData;
std::vector<glm::vec3> normalData;
std::vector<meshFaceIndex> faces;

std::ifstream fileStream(path);
if (!fileStream.is_open()){
    std::cerr << "ERROR: Could not open file '" << path << "!\n";
    return;
}
std::string lineBuffer;
while (std::getline(fileStream, lineBuffer)){
    std::stringstream lineStream(lineBuffer);
    std::string typeString;
    lineStream >> typeString;   // Get line token
    if (typeString == TOKEN_VPOS){  // Position
        glm::vec3 pos;
        lineStream >> pos.x >> pos.y >> pos.z;
        positionData.push_back(pos);
    }
    else{
        if (typeString == TOKEN_VUV){   // UV coord
            glm::vec2 UV;
            lineStream >> UV.x >> UV.y;
            uvData.push_back(UV);
        }
        else{
            if (typeString == TOKEN_VNORMAL){   // Normal
                glm::vec3 normal;
                lineStream >> normal.x >> normal.y >> normal.z;
                normalData.push_back(normal);
            }
            else{
                if (typeString == TOKEN_FACE){  // Face
                    meshFaceIndex faceIndex;
                    char interrupt;
                    for (int i = 0; i < 3; ++i){
                        lineStream >> faceIndex.positionIndex[i] >> interrupt
                            >> faceIndex.uvIndex[i] >> interrupt
                            >> faceIndex.normalIndex[i];
                    }
                    faces.push_back(faceIndex);
                }
            }
        }
    }
}
fileStream.close();     

std::vector<glm::vec3> packedPositions;
std::vector<glm::vec2> packedUVs;
std::vector<glm::vec3> packedNormals;

for (auto f : faces){
    Face face;  // Derp derp;
    for (auto i = 0; i < 3; ++i){
        if (!positionData.empty()){
            face.vertices[i].position = positionData[f.positionIndex[i] - 1];
            packedPositions.push_back(face.vertices[i].position);
        }
        else
            face.vertices[i].position = glm::vec3(0.0f);
        if (!uvData.empty()){
            face.vertices[i].uv = uvData[f.uvIndex[i] - 1];
            packedUVs.push_back(face.vertices[i].uv);
        }
        else
            face.vertices[i].uv = glm::vec2(0.0f);
        if (!normalData.empty()){
            face.vertices[i].normal = normalData[f.normalIndex[i] - 1];
            packedNormals.push_back(face.vertices[i].normal);
        }
        else
            face.vertices[i].normal = glm::vec3(0.0f);
    }
    myMesh.faces.push_back(face);
}

glGenVertexArrays(1, &(myMesh.gl_vaoID));
glBindVertexArray(myMesh.gl_vaoID);

GLuint positionBuffer;  // positions
glGenBuffers(1, &positionBuffer);
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3)*packedPositions.size(), &packedPositions[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

GLuint uvBuffer;    // uvs
glGenBuffers(1, &uvBuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2)*packedUVs.size(), &packedUVs[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);

GLuint normalBuffer;    // normals
glGenBuffers(1, &normalBuffer);
glBindBuffer(GL_ARRAY_BUFFER, normalBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3)*packedNormals.size(), &packedNormals[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);


glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);

.obj 加载例程主要改编自此例程: http://www.limegarden.net/2010/03/02/wavefront-obj-mesh-loader/

最佳答案

在我看来,这不像是深度测试问题,而更像是顶点/索引数组数据中的未对齐问题。请向我们展示您加载顶点缓冲区对象和元素缓冲区对象的代码。

关于c++ - OpenGL:Radeon 驱动程序似乎与深度测试混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24990637/

有关c++ - OpenGL:Radeon 驱动程序似乎与深度测试混淆的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  3. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  4. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  5. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  6. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  7. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

    刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

  8. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  9. ruby - 检查是否通过 require 执行或导入了 Ruby 程序 - 2

    如何检查Ruby文件是否是通过“require”或“load”导入的,而不是简单地从命令行执行的?例如:foo.rb的内容:puts"Hello"bar.rb的内容require'foo'输出:$./foo.rbHello$./bar.rbHello基本上,我想调用bar.rb以不执行puts调用。 最佳答案 将foo.rb改为:if__FILE__==$0puts"Hello"end检查__FILE__-当前ruby​​文件的名称-与$0-正在运行的脚本的名称。 关于ruby-检查是否

  10. ruby-on-rails - 如何在 Ruby on Rails 中实现由 JSF 2.0 (Primefaces) 驱动的 UI 魔法 - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道ruby​​onrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim

随机推荐