【问题标题】:glShaderSource access violation when using Win32 to read files使用Win32读取文件时glShaderSource访问冲突
【发布时间】:2020-03-20 04:01:08
【问题描述】:

所以,我正在尝试仅使用 Win32 API 和 OpenGL 设置基本的 OpenGL 场景,但我在加载着色器和 glShaderSource 函数时遇到了很大问题。我正在像这样阅读我的文件:

//HEADER

class FileReader
{
public:
    FileReader(const LPCSTR FileName);

    const void* GetFileData();

    ~FileReader();
private:

    HANDLE FileHandle;

    void* FileDataMemory;
};

//ACTUAL CODE

FileReader::FileReader(const LPCSTR FileName)
{
    FileHandle = CreateFileA(FileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if (FileHandle == INVALID_HANDLE_VALUE)
    {
        OutputDebugStringA("Failed to open file ");
        OutputDebugStringA(FileName);
        OutputDebugStringA(" for reading, application could not be loaded\n");
        ExitProcess(-2);
    }

    unsigned int FileSize = GetFileSize(FileHandle, 0);
    DWORD BytesRead;
    FileDataMemory = VirtualAlloc(0, FileSize, MEM_COMMIT, PAGE_READWRITE);
    ReadFile(FileHandle, FileDataMemory, FileSize, &BytesRead, 0);
    if (BytesRead < FileSize)
    {
        OutputDebugStringA("File was not read completely\n");
    }
}

const void* FileReader::GetFileData()
{
    return FileDataMemory;
}

FileReader::~FileReader()
{
    CloseHandle(FileHandle);
}

我使用这个类从光盘加载顶点着色器,如下所示:

    VertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(VertexShader, 1, static_cast<const GLchar* const*>(VertexShaderFile->GetFileData()), 0);

但是我的应用程序给了我一个访问冲突读取地址 0xFFFFFFFF 与 glShaderSource 联机。而且我很困惑,因为当我尝试在调试模式下查看这块内存时,它看起来很正常并且里面有正确的数据,所以我不知道该怎么办。

【问题讨论】:

  • 有什么特别的原因,为什么要限制自己使用 Win32 API?我能想到的唯一原因是,如果您想避免链接到 C 和/或 C++ 标准库,以减少可执行文件的大小。在创建演示或介绍时通常会这样做。但是对于那些您通常会将所有资产数据打包到可执行文件本身中的人。所以我对此有点疑惑。你通常不会直接使用 Win32 API,除非你是代码受虐狂。
  • 不,这只是为了学习目的,我决定创建一个简单的 OpenGL 应用程序(在这种情况下,简单的 OBJ 模型查看器具有纹理和阴影支持),没有任何库(只允许 GLEW,因为没有这真的变成了某种受虐狂)。

标签: c++ winapi opengl file-io


【解决方案1】:

从文件中读取的着色器源代码字符串不是以 0 结尾的。
预留FileSize+1字节的内存,确保缓冲区的最后一个字节为0。例如:

FileDataMemory = VirtualAlloc(0, FileSize+1, MEM_COMMIT, PAGE_READWRITE);
ZeroMemory(FileDataMemory, FileSize+1);
ReadFile(FileHandle, FileDataMemory, FileSize, &BytesRead, 0);

此外,glShaderSource 的第三个参数是一个字符串数组 (const GLchar **):

const GLchar *source = static_cast<const GLchar*>(VertexShaderFile->GetFileData());
glShaderSource(VertexShader, 1, &source, 0);

您在代码中实际执行的是转换VertexShaderFile-&gt;GetFileData()。你需要做什么才能投 &amp;VertexShaderFile-&gt;GetFileData()


此外,我建议使用 STL 来读取着色器源文件。例如:

std::ifstream sourceFile(FileName, std::fstream::in); 
std::string sourceCode = std::string( 
    std::istreambuf_iterator<char>(sourceFile),
    std::istreambuf_iterator<char>());

【讨论】:

  • @Poseydon42 我已经扩展了答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-23
  • 2021-10-27
  • 1970-01-01
  • 1970-01-01
  • 2015-07-31
  • 2018-08-31
  • 1970-01-01
相关资源
最近更新 更多