- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在 C++ 中开发 OpenGL 应用程序已经几个月了,以前从未遇到过这个问题。
在 Visual Studio 2012 中编码我可以在 IDE 中运行应用程序或手动启动可执行文件。在这两种情况下,我都可以在调试版本和发布版本之间进行选择。以下问题仅在我自己启动发布构建可执行文件时出现。否则一切正常。
当我将新表单动态添加到场景中时,应用程序有时会崩溃。我的操作系统 Windows 8 64bit 允许我从崩溃对话框中调试程序
这确实没有太大帮助,因为它是一个发布版本,在运行时可用的调试信息较少,但它至少告诉我应用程序在绘图调用 glDrawTriangles()
附近崩溃。在我的代码中,一个循环内只有一个绘制调用。
崩溃只是不定期发生,这让我抓狂。有时应用程序可以很好地运行几分钟,有时会立即崩溃,有时会运行几秒钟。但我认为知道应用程序只会在我首先在另一个线程中生成并在主线程中创建 OpenGL 缓冲区的场景中插入新表单后立即崩溃是很重要的。
以下是 Windows 崩溃对话框中显示的问题详细信息。看来我的视频卡驱动程序 ATI Radeon 7870 崩溃了。
Problem signature:
Problem Event Name: APPCRASH
Application Name: Application.exe
Application Version: 0.0.0.0
Application Timestamp: 50f1491a
Fault Module Name: atioglxx.dll
Fault Module Version: 6.14.10.11931
Fault Module Timestamp: 50650037
Exception Code: c0000005
Exception Offset: 001108ef
OS Version: 6.2.9200.2.0.0.256.27
Locale ID: 1031
Additional Information 1: 5861
Additional Information 2: 5861822e1919d7c014bbb064c64908b2
Additional Information 3: dac6
Additional Information 4: dac6c2650fa14dd558bd9f448e23afd1Read our privacy statement online:
http://go.microsoft.com/fwlink/?linkid=190175If the online privacy statement is not available, please read our privacy statement offline:
C:\Windows\system32\en-US\erofflps.txt
到目前为止,我所做的是更新我的视频卡驱动程序并调试我的应用程序,因为我注意到结果不可靠,因为崩溃是自发发生的。有很多源文件,老实说我不确定是哪个导致了这个错误。它可能是一个名为 terrain.cpp
的文件,因此我将代码粘贴到此处。
#pragma once
#include "system.h"
#include "debug.h"
#include <vector>
#include <cstdlib>
#include <future>
using namespace std;
#include <GLEW/glew.h>
#include <SFML/OpenGL.hpp>
#include <SFML/Graphics/Image.hpp>
using namespace sf;
#include <GLM/glm.hpp>
#include <GLM/gtc/noise.hpp>
using namespace glm;
#include "settings.h"
#include "camera.h"
#include "form.h"
#include "transform.h"
#include "terrain.h"
#include "shader.h"
#include "movement.h"
typedef detail::tvec3<int> vec3i;
class ComponentTerrain : public Component
{
void Init()
{
auto wld = Global->Add<StorageTerrain>("terrain");
tasking = false;
Texture();
Listeners();
}
void Update()
{
auto wld = Global->Get<StorageTerrain>("terrain");
auto stg = Global->Get<StorageSettings>("settings");
auto cam = Global->Get<StorageCamera>("camera");
auto cks = Entity->Get<StorageChunk>();
int Distance = (int)(.5f * stg->Viewdistance / CHUNK_X / 2);
Debug::Info("Terrain chunk distance " + to_string(Distance));
for(int X = -Distance; X <= Distance; ++X)
for(int Z = -Distance; Z <= Distance; ++Z)
{
addChunk(X + (int)cam->Position.x / CHUNK_X, 0, Z + (int)cam->Position.z / CHUNK_Z);
}
for(auto chunk : wld->chunks)
{
auto chk = cks.find(chunk.second);
float distance = (float)vec3(chunk.first[0] * CHUNK_X - cam->Position.x, chunk.first[1] * CHUNK_Y - cam->Position.y, chunk.first[2] * CHUNK_Z - cam->Position.z).length();
if(distance > stg->Viewdistance)
deleteChunk(chunk.first[0], chunk.first[1], chunk.first[2]);
}
if(tasking)
{
if(task.wait_for(chrono::milliseconds(0)) == future_status::ready)
{
tasking = false;
Data data = task.get();
Buffers(data);
}
}
else
{
for(auto chunk : cks)
if(chunk.second->changed)
{
tasking = true;
chunk.second->changed = false;
task = async(launch::async, &ComponentTerrain::Mesh, this, Data(chunk.first));
break;
}
}
}
struct Data
{
Data() {}
Data(unsigned int id) : id(id) {}
unsigned int id;
vector<float> Vertices, Normals, Texcoords;
vector<int> Elements;
};
future<Data> task;
bool tasking;
Image texture;
void Listeners()
{
Event->Listen("SystemInitialized", [=]{
auto cam = Global->Get<StorageCamera>("camera");
cam->Position = vec3(0, CHUNK_Y, 0);
cam->Angles = vec2(0.75, -0.25);
});
Event->Listen("InputBindChunk", [=]{
addChunk(rand() % 5, 0, rand() % 5);
addChunk(rand() % 5, 0, rand() % 5);
addChunk(rand() % 5, 0, rand() % 5);
});
}
unsigned int getChunk(int X, int Y, int Z)
{
auto wld = Global->Get<StorageTerrain>("terrain");
array<int, 3> key = {X, Y, Z};
auto i = wld->chunks.find(key);
return (i != wld->chunks.end()) ? i->second : 0;
}
int addChunk(int X, int Y, int Z)
{
auto wld = Global->Get<StorageTerrain>("terrain");
auto shd = Global->Get<StorageShader>("shader"); // moved this line
unsigned int id = getChunk(X, Y, Z);
if(!id)
{
id = Entity->New();
Entity->Add<StorageChunk>(id);
auto frm = Entity->Add<StorageForm>(id); // moved this line
auto tsf = Entity->Add<StorageTransform>(id);
frm->Program = shd->Program; // moved this line
tsf->Position = vec3(X * CHUNK_X, Y * CHUNK_Y, Z * CHUNK_Z);
Generate(id, X, Y, Z);
array<int, 3> key = {X, Y, Z};
wld->chunks.insert(make_pair(key, id));
}
return id;
}
void deleteChunk(int X, int Y, int Z)
{
auto wld = Global->Get<StorageTerrain>("terrain");
unsigned int id = getChunk(X, Y, Z);
if(id < 1) return;
array<int, 3> key = {X, Y, Z};
wld->chunks.erase(key);
Entity->Delete<StorageChunk>(id);
Entity->Delete<StorageForm>(id);
Entity->Delete<StorageTransform>(id);
// free buffers
}
void Generate(unsigned int id, int X, int Y, int Z)
{
auto cnk = Entity->Get<StorageChunk>(id);
cnk->changed = true;
for(int x = 0; x < CHUNK_X; ++x) {
const float i = X + (float)x / CHUNK_X;
for(int z = 0; z < CHUNK_Z; ++z) {
const float j = Z + (float)z / CHUNK_Z;
double height_bias = 0.30;
double height_base = 0.50 * (simplex(0.2f * vec2(i, j)) + 1) / 2;
double height_fine = 0.20 * (simplex(1.5f * vec2(i, j)) + 1) / 2;
int height = (int)((height_bias + height_base + height_fine) * CHUNK_Y);
for(int y = 0; y < height; ++y) cnk->blocks[x][y][z] = true;
} }
}
#define TILES_U 4
#define TILES_V 4
Data Mesh(Data data)
{
auto cnk = Entity->Get<StorageChunk>(data.id);
auto *Vertices = &data.Vertices, *Normals = &data.Normals, *Texcoords = &data.Texcoords;
auto *Elements = &data.Elements;
const vec2 grid(1.f / TILES_U, 1.f / TILES_V);
int n = 0;
for(int X = 0; X < CHUNK_X; ++X)
for(int Y = 0; Y < CHUNK_Y; ++Y)
for(int Z = 0; Z < CHUNK_Z; ++Z)
if(cnk->blocks[X][Y][Z])
{
int Tile = Clamp(rand() % 2 + 1, 0, TILES_U * TILES_V - 1);
for(int dim = 0; dim < 3; ++dim) { int dir = -1; do {
vec3i neigh = Shift(dim, vec3i(dir, 0, 0)) + vec3i(X, Y, Z);
if(Inside(neigh, vec3i(0), vec3i(CHUNK_X, CHUNK_Y, CHUNK_Z) - 1))
if(cnk->blocks[neigh.x][neigh.y][neigh.z])
{ dir *= -1; continue; }
for(float i = 0; i <= 1; ++i)
for(float j = 0; j <= 1; ++j)
{
vec3 vertex = vec3(X, Y, Z) + floatify(Shift(dim, vec3i((dir+1)/2, i, j)));
Vertices->push_back(vertex.x); Vertices->push_back(vertex.y); Vertices->push_back(vertex.z);
}
vec3 normal = normalize(floatify(Shift(dim, vec3i(dir, 0, 0))));
for(int i = 0; i < 4; ++i)
{
Normals->push_back(normal.x); Normals->push_back(normal.y); Normals->push_back(normal.z);
}
vec2 position = (vec2(Tile % TILES_U, Tile / TILES_U) + .25f) * grid;
Texcoords->push_back(position.x); Texcoords->push_back(position.y);
Texcoords->push_back(position.x + grid.x/2); Texcoords->push_back(position.y);
Texcoords->push_back(position.x); Texcoords->push_back(position.y + grid.y/2);
Texcoords->push_back(position.x + grid.x/2); Texcoords->push_back(position.y + grid.y/2);
if(dir == -1) {
Elements->push_back(n+0); Elements->push_back(n+1); Elements->push_back(n+2);
Elements->push_back(n+1); Elements->push_back(n+3); Elements->push_back(n+2);
} else {
Elements->push_back(n+0); Elements->push_back(n+2); Elements->push_back(n+1);
Elements->push_back(n+1); Elements->push_back(n+2); Elements->push_back(n+3);
}
n += 4;
dir *= -1; } while(dir > 0); }
}
return data;
}
void Buffers(Data data)
{
auto frm = Entity->Get<StorageForm>(data.id);
glGenBuffers(1, &frm->Positions);
glBindBuffer(GL_ARRAY_BUFFER, frm->Positions);
glBufferData(GL_ARRAY_BUFFER, data.Vertices.size() * sizeof(float), &(data.Vertices[0]), GL_STATIC_DRAW);
glGenBuffers(1, &frm->Normals);
glBindBuffer(GL_ARRAY_BUFFER, frm->Normals);
glBufferData(GL_ARRAY_BUFFER, data.Normals.size() * sizeof(float), &(data.Normals[0]), GL_STATIC_DRAW);
glGenBuffers(1, &frm->Texcoords);
glBindBuffer(GL_ARRAY_BUFFER, frm->Texcoords);
glBufferData(GL_ARRAY_BUFFER, data.Texcoords.size() * sizeof(float), &(data.Texcoords[0]), GL_STATIC_DRAW);
glGenBuffers(1, &frm->Elements);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, frm->Elements);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.Elements.size() * sizeof(int), &data.Elements[0], GL_STATIC_DRAW);
glGenTextures(1, &frm->Texture);
glBindTexture(GL_TEXTURE_2D, frm->Texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.getSize().x, texture.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture.getPixelsPtr());
glGenerateMipmap(GL_TEXTURE_2D);
}
void Texture()
{
Image image;
bool result = image.loadFromFile("forms/textures/terrain.png");
if(!result){ Debug::Fail("Terrain texture loading fail"); return; }
Vector2u size = Vector2u(image.getSize().x / TILES_U, image.getSize().y / TILES_V);
texture.create(image.getSize().x * 2, image.getSize().y * 2, Color());
for(int u = 0; u < TILES_U; ++u)
for(int v = 0; v < TILES_V; ++v)
{
Image tile, quarter;
tile.create(size.x, size.y, Color());
tile.copy(image, 0, 0, IntRect(size.x * u, size.y * v, size.x, size.y), true);
quarter.create(size.x, size.y, Color());
quarter.copy(tile, 0, 0, IntRect(size.x / 2, size.y / 2, size.x / 2, size.y / 2), true);
quarter.copy(tile, size.x / 2, 0, IntRect(0, size.y / 2, size.x / 2, size.y / 2), true);
quarter.copy(tile, 0, size.y / 2, IntRect(size.x / 2, 0, size.x / 2, size.y / 2), true);
quarter.copy(tile, size.x / 2, size.y / 2, IntRect(0, 0, size.x / 2, size.y / 2), true);
texture.copy(quarter, (u * 2 ) * size.x, (v * 2 ) * size.y, IntRect(0, 0, 0, 0), true);
texture.copy(quarter, (u * 2 + 1) * size.x, (v * 2 ) * size.y, IntRect(0, 0, 0, 0), true);
texture.copy(quarter, (u * 2 ) * size.x, (v * 2 + 1) * size.y, IntRect(0, 0, 0, 0), true);
texture.copy(quarter, (u * 2 + 1) * size.x, (v * 2 + 1) * size.y, IntRect(0, 0, 0, 0), true);
}
}
template <typename T>
inline T Clamp(T Value, T Min, T Max)
{
if(Value < Min) return Min;
if(Value > Max) return Max;
return Value;
}
bool Inside(vec3i Position, vec3i Min, vec3i Max)
{
if(Position.x < Min.x || Position.y < Min.y || Position.z < Min.z) return false;
if(Position.x > Max.x || Position.y > Max.y || Position.z > Max.z) return false;
return true;
}
inline vec3i Shift(int Dimension, vec3i Vector)
{
if (Dimension % 3 == 1) return vec3i(Vector.z, Vector.x, Vector.y);
else if (Dimension % 3 == 2) return vec3i(Vector.y, Vector.z, Vector.x);
else return Vector;
}
vec3 floatify(vec3i Value)
{
return vec3(Value.x, Value.y, Value.z);
}
};
但是,您可以找到 whole code on Github .
您知道什么可能导致崩溃或如何找到错误吗?如果您需要更多信息以及需要哪种信息,请告诉我。
感谢@doomster,我现在可以找到并修复错误。
渲染器组件循环遍历一个表单 vector 来绘制它们。异步线程向该 vector 添加了新形式,但它们的缓冲区稍后在生成的顶点返回后在主线程中创建。这意味着绘图和添加表格是并行进行的。当呈现器尝试呈现尚未创建任何缓冲区的表单时发生崩溃。
我在上面的代码中插入了注释以突出显示我从 addChunk()
移动到 Buffers()
的三行以解决问题。我仍然不知道为什么只有发布版本的可执行文件崩溃了,但这已经不重要了。
最佳答案
这里我要验证两件事:
future<T>
.我不确定,但如果它在不同的线程中运行,那可能会对 OpenGL 产生负面影响,我听说它对多线程使用很敏感。尽管将此视为谣言,但我对此并不确定,但尝试转换为单线程代码值得一试。关于c++ - OpenGL 应用程序有时会崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14293132/
在 OpenGL/ES 中,在实现渲染到纹理功能时,您必须小心,不要引起反馈循环(从正在写入的同一纹理中读取像素)。由于显而易见的原因,当您读取和写入纹理的相同像素时,行为是未定义的。但是,如果您正在
正如我们最终都知道的那样,规范是一回事,实现是另一回事。大多数错误是我们自己造成的,但有时情况并非如此。 我相信列出以下内容会很有用: GPU 驱动程序中当前已知的与最新版本的 OpenGL 和 GL
很难说出这里问的是什么。这个问题是模棱两可的、模糊的、不完整的、过于宽泛的或修辞的,无法以目前的形式得到合理的回答。为了帮助澄清这个问题以便可以重新打开它,visit the help center
我正在学习 OpenGL,非常想知道与显卡的交互如何。 我觉得了解它是如何在图形驱动程序中实现的,会让我了解 opengl 的完整内部结构(通过这个我可以知道哪些阶段/因素影响我对 opengl 性能
我正在尝试绘制到大于屏幕尺寸(即 320x480)的渲染缓冲区 (512x512)。 执行 glReadPixels 后,图像看起来是正确的,除非图像的尺寸超过屏幕尺寸——在本例中,超过 320 水平
我正在 Windows 中制作一个 3D 小行星游戏(使用 OpenGL 和 GLUT),您可以在其中穿过一堆障碍物在太空中移动并生存下来。我正在寻找一种方法来针对无聊的 bg 颜色选项设置图像背景。
如果我想要一个包含 100 个 10*10 像素 Sprite 的 Sprite 表,是否可以将它们全部排成一排来制作 1,000*10 像素纹理?还是 GPU 对不那么窄的纹理表现更好?这对性能有什
这个问题在这里已经有了答案: Rendering 2D sprites in a 3D world? (7 个答案) 关闭 6 年前。 我如何概念化让图像始终面对相机。我尝试将三角函数与 arcta
是否可以在 OpenGL 中增加缓冲区? 假设我想使用实例化渲染。每次在世界上生成一个新对象时,我都必须用实例化数据更新缓冲区。 在这种情况下,我有一个 3 个 float 的缓冲区 std::v
有人可以向我解释为什么下面的代码没有绘制任何东西,但如果我使用 GL_LINE_LOOP 它确实形成了一个闭环吗? glBegin(GL_POLYGON); for(int i = 0; i <= N
正如标题所说,OpenGL 中的渲染目标是什么?我对 OpenGL 很陌生,我看到的所有网站都让我很困惑。 它只是一个缓冲区,我在其中放置稍后将用于渲染的东西吗? 如果您能提供一个很好的引用来阅读它,
当使用 OpenGL 1.4 固定功能多纹理时,每个纹理阶段的输出在传递到下一个阶段之前是否都固定在 [0, 1]? spec说(第 153 页): If the value of TEXTURE_E
我比较了 2 个函数 openGL ES 和 openGL gvec4 texelFetchOffset(gsampler2DArray sampler, ivec3 P, int lod, ivec
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 10 年前。 Improve thi
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 6年前关闭。 Improve this qu
那么当你调用opengl函数时,比如glDraw或者gLBufferData,是否会导致程序线程停止等待GL完成调用呢? 如果不是,那么 GL 如何处理调用像 glDraw 这样的重要函数,然后立即更
我正在尝试实现级联阴影贴图,当我想访问我的视锥体的每个分区的相应深度纹理时,我遇到了一个错误。 更具体地说,当我想选择正确的阴影纹理时会出现我的问题,如果我尝试下面的代码,我会得到一个像 this 中
我想为OpenGL ES和OpenGL(Windows)使用相同的着色器源。为此,我想定义自定义数据类型并仅使用OpenGL ES函数。 一种方法是定义: #define highp #define
我尝试用 6 个位图映射立方体以实现天空盒效果。我的问题是一个纹理映射到立方体的每个面。我已经检查了 gDEBugger,在立方体纹理内存中我只有一个 图像(因为我尝试加载六个图像)。 代码准备纹理:
在 OpenGL 中偏移深度的最佳方法是什么?我目前每个多边形都有索引顶点属性,我将其传递给 OpenGL 中的顶点着色器。我的目标是在深度上偏移多边形,其中最高索引始终位于较低索引的前面。我目前有这
我是一名优秀的程序员,十分优秀!