Ошибка связывания шейдеров на графике NVidia против Intel - PullRequest
0 голосов
/ 19 ноября 2018

У меня проблема с моей программой GLFW / C ++, из-за которой у меня возникает проблема, из-за которой шейдеры будут правильно компилироваться и связываться на графическом процессоре NVIDIA, но не на интегрированной графической карте Intel. Я часами пытался исправить это для школьного проекта, но, похоже, ничего не получилось. Шейдеры будут правильно компилироваться на стороне Intel, но не смогут связать шейдеры.

Я знаю, что с самими шейдерами все в порядке, потому что они работают в других проектах, которые я делал, но в этом конкретном случае это не получается.

Вот код для связи шейдера

void ResourceManager::LoadMaterial(const std::string name, const char *prefix){

    // Load vertex program source code
    std::string filename = std::string(prefix) + std::string(VERTEX_PROGRAM_EXTENSION);
    std::string vp = LoadTextFile(filename.c_str());

    // Load fragment program source code
    filename = std::string(prefix) + std::string(FRAGMENT_PROGRAM_EXTENSION);
    std::string fp = LoadTextFile(filename.c_str());

    // Create a shader from the vertex program source code
    GLuint vs = glCreateShader(GL_VERTEX_SHADER);
    const char *source_vp = vp.c_str();
    glShaderSource(vs, 1, &source_vp, NULL);
    glCompileShader(vs);

    // Check if shader compiled successfully
    GLint status;
    glGetShaderiv(vs, GL_COMPILE_STATUS, &status);
    if (status != GL_TRUE){
        char buffer[512];
        glGetShaderInfoLog(vs, 512, NULL, buffer);
        throw(std::ios_base::failure(std::string("Error compiling vertex shader: ")+std::string(buffer)));
    }

    // Create a shader from the fragment program source code
    GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
    const char *source_fp = fp.c_str();
    glShaderSource(fs, 1, &source_fp, NULL);
    glCompileShader(fs);

    // Check if shader compiled successfully
    glGetShaderiv(fs, GL_COMPILE_STATUS, &status);
    if (status != GL_TRUE){
        char buffer[512];
        glGetShaderInfoLog(fs, 512, NULL, buffer);
        throw(std::ios_base::failure(std::string("Error compiling fragment shader: ")+std::string(buffer)));
    }

    // Create a shader program linking both vertex and fragment shaders
    // together
    GLuint sp = glCreateProgram();
    glAttachShader(sp, vs);
    glAttachShader(sp, fs);
    glLinkProgram(sp);

    // Check if shaders were linked successfully
    glGetProgramiv(sp, GL_LINK_STATUS, &status);
    if (status != GL_TRUE){
        char buffer[512];
        glGetShaderInfoLog(sp, 512, NULL, buffer);
        throw(std::ios_base::failure(std::string("Error linking shaders: ")+std::string(buffer)));
    }

    // Delete memory used by shaders, since they were already compiled
    // and linked
    glDeleteShader(vs);
    glDeleteShader(fs);

    // Add a resource for the shader program
    AddResource(Material, name, sp, 0);
}

Если вам нужны другие части кода, я с радостью предоставлю вам больше информации, но, похоже, именно здесь со стороны Intel происходит сбой.

Я действительно надеюсь, что есть просто мертвое исправление, которого я не нашел, потому что это очень сложная проблема. Заранее спасибо.

приложение № 1: код ошибки

Error linking shaders: ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠: iostream stream error

Приложение № 2 Cmake code

    cmake_minimum_required(VERSION 2.6)

# Name of project
project(IlluminationDemo)

# Specify project files: header files and source files
set(HDRS
    asteroid.h camera.h game.h model_loader.h resource.h resource_manager.h scene_graph.h scene_node.h
)

set(SRCS
    asteroid.cpp camera.cpp game.cpp main.cpp resource.cpp resource_manager.cpp scene_graph.cpp scene_node.cpp material_fp.glsl material_vp.glsl metal_fp.glsl metal_vp.glsl plastic_fp.glsl plastic_vp.glsl textured_material_fp.glsl textured_material_vp.glsl three-term_shiny_blue_fp.glsl three-term_shiny_blue_vp.glsl three-term_textured_fp.glsl three-term_textured_vp.glsl three-term_toon_fp.glsl three-term_toon_vp.glsl
)

# Add path name to configuration file
configure_file(path_config.h.in path_config.h)

# Add executable based on the source files
add_executable(IlluminationDemo ${HDRS} ${SRCS})

# Require OpenGL library
find_package(OpenGL REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR})
target_link_libraries(IlluminationDemo ${OPENGL_gl_LIBRARY})

# Other libraries needed
set(LIBRARY_PATH "" CACHE PATH "Folder with GLEW, GLFW, GLM, and SOIL libraries")
include_directories(${LIBRARY_PATH}/include)
if(NOT WIN32)
    find_library(GLEW_LIBRARY GLEW)
    find_library(GLFW_LIBRARY glfw)
    find_library(SOIL_LIBRARY SOIL)
elseif(WIN32)
    find_library(GLEW_LIBRARY glew32s HINTS ${LIBRARY_PATH}/lib)
    find_library(GLFW_LIBRARY glfw3 HINTS ${LIBRARY_PATH}/lib)
    find_library(SOIL_LIBRARY SOIL HINTS ${LIBRARY_PATH}/lib)
endif(NOT WIN32)
target_link_libraries(IlluminationDemo ${GLEW_LIBRARY})
target_link_libraries(IlluminationDemo ${GLFW_LIBRARY})
target_link_libraries(IlluminationDemo ${SOIL_LIBRARY})

# The rules here are specific to Windows Systems
if(WIN32)
    # Avoid ZERO_CHECK target in Visual Studio
    set(CMAKE_SUPPRESS_REGENERATION TRUE)

    # This will use the proper libraries in debug mode in Visual Studio
    set_target_properties(IlluminationDemo PROPERTIES DEBUG_POSTFIX _d)
endif(WIN32)

Приложение № 3, код шейдера

Фрагмент шейдера

// Illumination based on the traditional three-term model

#version 130

// Attributes passed from the vertex shader
in vec3 position_interp;
in vec3 normal_interp;
in vec3 light_pos[2];
in vec3 camera_pos;

// Material attributes (constants)
vec4 ambient_color = vec4(0.0, 0.1, 0.0, 1.0);
vec4 diffuse_color = vec4(0.4, 0.8, 0.3, 1.0);
vec4 specular_color = vec4(0.9, 0.9, 0.9, 1.0);
float phong_exponent = 128.0;


void main() 
{
    // Blinn-Phong shading

    vec3 N, // Interpolated normal for fragment
         L, // Light-source direction
         V, // View direction
         H; // Half-way vector
    for(int i = 0; i < light_pos.length; i++){
    // Compute Lambertian lighting Id
    N = normalize(normal_interp);


    L = (light_pos[i] - position_interp);
    L = normalize(L);

    float Id = max(dot(N, L), 0.0);
    Id = round(Id*2.0) / 2.0;

    // Compute specular term for Blinn-Phong shading
    // V = (eye_position - position_interp);
    V = camera_pos - position_interp; // Eye position is (0, 0, 0) in view coordinates
    V = normalize(V);

    //H = 0.5*(V + L); // Halfway vector
    H = (V + L); // Halfway vector
    H = normalize(H);

    float spec_angle_cos = max(dot(N, H), 0.0);
    float Is = pow(spec_angle_cos, phong_exponent);
    Is = round(Is*2.0) / 2.0;

    if(dot(V,N) > mix(0.5, 0.5, max(0.0, dot(N,L)))){
    // Assign light to the fragment
    gl_FragColor += ambient_color + Id*diffuse_color + Is*specular_color;
    } else {

        gl_FragColor = vec4(0.0,0.0,0.0,1.0) * (ambient_color + Id*diffuse_color + Is*specular_color);
    }
    }


    // For debug, we can display the different values
    //gl_FragColor = ambient_color;
    //gl_FragColor = diffuse_color;
    //gl_FragColor = specular_color;
    //gl_FragColor = color_interp;
    //gl_FragColor = vec4(N.xyz, 1.0);
    //gl_FragColor = vec4(L.xyz, 1.0);
    //gl_FragColor = vec4(V.xyz, 1.0);
}

// Illumination based on the traditional three-term model

Вершинный шейдер

#version 130

// Vertex buffer
in vec3 vertex;
in vec3 normal;
in vec3 color;

// Uniform (global) buffer
uniform mat4 world_mat;
uniform mat4 view_mat;
uniform mat4 projection_mat;
uniform mat4 normal_mat;
uniform vec3 cameraPos;

// Attributes forwarded to the fragment shader
out vec3 position_interp;
out vec3 normal_interp;
out vec3 camera_pos;
out vec3 light_pos[2];

// Material attributes (constants)
//
// Could be loaded from a configuration file and also passed with the
// uniform buffer
vec3 light_position = vec3(-0.5, -0.5, 1.5);
vec3 light_position2 = vec3(4.0, -1.0, -1.0);


void main()
{
    camera_pos = cameraPos;
    // Transform vertex position
    gl_Position = projection_mat * view_mat * world_mat * vec4(vertex, 1.0);

    // Transform vertex position without including projection
    position_interp = vec3(view_mat * world_mat * vec4(vertex, 1.0));

    // Transform normal
    normal_interp = vec3(normal_mat * vec4(normal, 0.0));

    // Transform light position to align with view
    light_pos[0] = vec3(view_mat * vec4(light_position, 1.0));
    light_pos[1] = vec3(view_mat * vec4(light_position2, 1.0));
}

Добавление # 4 Похоже, проблема связана с тем, как массив light_pos [] передается между шейдерами, после чего программа выходит из себя при вызове light_pos.length. Разъяснение по этому вопросу будет оценено.

Приложение № 5 Протестированные графические адаптеры: Intel: HD 4600, HD 5600, HD 615 ,, NVidia: GTX 750 ti, GTX 1080, GTX 970 м

1 Ответ

0 голосов
/ 20 ноября 2018

Как четко указано в Версия спецификации GLSL 1.30;5.7. Структура и операции с массивами;страница 46 , length - это метод, а не член, и правильный синтаксис для использования:

vec3 light_pos[2];

int l = light_pos.length();

Для решения вашей проблемы измените light_pos.length на light_pos.length().

Конечно, все еще удивительно, что компилятор не генерирует сообщение об ошибке в этом случае.
В моем случае драйвер NVIDIA принял light_pos.length, как если бы это было light_pos.length().
Конечно,Драйвер Intel HD принят light_pos.length().Использование light_pos.length не выдало сообщения об ошибке, но вызывает нарушение прав доступа на glLinkProgram.

...