簡體   English   中英

OpenGL 着色器有時編譯有時不編譯

[英]OpenGL Shaders sometimes compile and sometimes not

我正在學習 OpenGL,當我運行程序時,有時可以工作(紅色三角形),有時不能(白色三角形,沒有三角形)。 我正在使用 makefile 使用 msvc(命令行中的 cl.exe)對其進行編譯。 這是該程序的簡化版本,如果您也遇到相同的奇怪行為,請告訴我。

預期結果(10% 的運行)

:D

越野車結果(90% 的運行)

:C

:C

主文件

#define SDL_MAIN_HANDLED
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <sstream>
#include <GL/glew.h>
#include <SDL2/SDL.h>
//Loading the file, I suspect that the shaders sometimes are not loaded properly but I'm not sure.
std::string loadFile(const std::string filepath)
{
    std::ifstream file(filepath.c_str());
    if(!file.is_open())
    {
        std::cerr << "Error loading Shader" << std::endl;
        std::exit(1);
    }
    std::string output = std::string((std::istreambuf_iterator<char>(file)),std::istreambuf_iterator<char>());
    return output;
}
//Just error checking (Probably I should include the shader validation here)
void checkProgramError(GLuint program)
{
    GLint success = 0;
    char infolog[1024] = {};
    glGetProgramiv(program,GL_LINK_STATUS,&success);
    if(!success)
    {
        glGetProgramInfoLog(program,1024,nullptr,infolog);
        std::cerr << infolog << std::endl;
    }
}

void checkShaderError(GLuint shader)
{
    GLint success = 0;
    char infolog[1024] = {};
    glGetShaderiv(shader,GL_COMPILE_STATUS,&success);
    if(!success)
    {
        glGetShaderInfoLog(shader,1024,nullptr,infolog);
        std::cerr << infolog << std::endl;
    }
}
/*
In my folder:
|basicShader.vs
|basicShader.fs
|main.cpp
|makefile
*/
GLuint createProgram(std::string name)
{
    const char* vertex_shader_source = loadFile(name + ".vs").c_str();
    const char* fragment_shader_source = loadFile(name + ".fs").c_str();

    GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex_shader,1,&vertex_shader_source,nullptr);
    glCompileShader(vertex_shader);
    checkShaderError(vertex_shader);

    GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragment_shader,1,&fragment_shader_source,nullptr);
    checkShaderError(fragment_shader);

    GLuint program = glCreateProgram();
    glAttachShader(program,vertex_shader);
    glAttachShader(program,fragment_shader);
    glLinkProgram(program);
    checkProgramError(program);
    glValidateProgram(program);

    return program;
}
int main(int argc,char* argv)
{
    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION,1);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION,4);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,8);
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE,8);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8);
    SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE,32);
    SDL_Window* window = SDL_CreateWindow("Ventana",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,600,600,SDL_WINDOW_OPENGL);
    SDL_GL_CreateContext(window);
    GLenum error = glewInit();
    if(error != GLEW_OK){
        printf("Error: Problemas al iniciar glew\n");
        printf("Error: %s",glewGetErrorString(error));
    }

    float first_triangle[] = {
        0.5f, -0.5f, 0.0f,   
        -0.5f, -0.5f, 0.0f,  
        0.0f,  0.5f, 0.0f,   
    };
    //Create and config mesh
    GLuint VAO,VBO;
    glGenVertexArrays(1,&VAO);
    glGenBuffers(1,&VBO);

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER,VBO);
    glBufferData(GL_ARRAY_BUFFER,sizeof(first_triangle),&first_triangle,GL_STATIC_DRAW);

    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,0);
    glEnableVertexAttribArray(0);

    glBindVertexArray(0);
    //Load and enable shader
    GLuint program = createProgram("basicShader");
    glUseProgram(program);

    for(bool running = true;running;)
    {   SDL_Event event;
        while(SDL_PollEvent(&event))
            if(event.type == SDL_QUIT) running = false;
        //Clear Screen
        glClearColor(0.0,0.7,0.3,1.0);
        glClear(GL_COLOR_BUFFER_BIT);

        //Draw mesh
        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES,0,3);
        glBindVertexArray(0);

        SDL_GL_SwapWindow(window);
    }

    return 0;
}

basicShader.vs (頂點着色器)

#version 120
attribute vec3 aPos;

void main()
{
    gl_Position = vec4(aPos,1.0);
}

basicShader.fs (片段着色器)

#version 120

void main()
{
    gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}

makefile

LIBS=SDL2.lib SDL2main.lib opengl32.lib glu32.lib glew32.lib
CXX=cl 
CFLAGS=/std:c++17 /EHsc /Zi
SOURCES=main.cpp 

all :main.cpp
    $(CXX) $(CFLAGS) $(SOURCES) /Fe:main.exe $(LIBS) /link /subsystem:console
    main.exe

如果您安裝了 BuildTools,您可以使用以下命令在終端中獲取 cl.exe:

CMD: "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat"
POWERSHELL: cmd.exe /k '"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat" & powershell'

您在這里調用未定義的行為:

 const char* vertex_shader_source = loadFile(name + ".vs").c_str();

load_file()返回std::string存儲在此處的臨時文件中,並在表達式結束后立即被銷毀,給您留下一個指向 memory 的懸空指針,該指針由現已銷毀的 object 使用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM