2016-09-05 66 views
0

我正在嘗試將一些照明應用於紋理。 我創建了一個紋理立方體,並在其中放置了一個相機。 現在,我想點亮它的內在面孔。我已經告訴我應該使用着色器,所以我看了很多教程和我創建:用着色器在OpenGL中照明

頂點着色器:

const GLchar* vertexSkySource = 
#if defined(__APPLE_CC__) 
"#version 150 core\n" 
#else 
"#version 130\n" 
#endif 
"uniform mat3 view_rot;" 
"in vec3 position;" 
"out vec3 Coord;" 
"void main() {" 
" Coord = view_rot * position;" 
" gl_Position = vec4(position, 1.0);" 
"}"; 

片段着色器

const GLchar* fragmentSkySource = 
#if defined(__APPLE_CC__) 
"#version 150 core\n" 
#else 
"#version 130\n" 
#endif 
"in vec3 Coord;" 
"out vec4 outColor;" 
"uniform samplerCube textureSampler;" 
"void main() {" 
" outColor = texture(textureSampler, Coord);" 
"}"; 

我後初始化它們

void initialize_shader() 
{ 
    // shader per la skybox 
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); 
    glShaderSource(vertexShader, 1, &vertexSkySource, NULL); 
    glCompileShader(vertexShader); 
    { 
     GLchar log[512]; 
     GLsizei slen = 0; 
     glGetShaderInfoLog(vertexShader, 512, &slen, log); 
     if (slen) 
      std::cerr << log << std::endl; 
    } 

    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 
    glShaderSource(fragmentShader, 1, &fragmentSkySource, NULL); 
    glCompileShader(fragmentShader); 
    { 
     GLchar log[512]; 
     GLsizei slen = 0; 
     glGetShaderInfoLog(fragmentShader, 512, &slen, log); 
     if (slen) 
      std::cerr << log << std::endl; 
    } 

    skyProgram = glCreateProgram(); 
    glAttachShader(skyProgram, vertexShader); 
    glAttachShader(skyProgram, fragmentShader); 
    glBindFragDataLocation(skyProgram, 0, "outColor"); 
    glLinkProgram(skyProgram); 
    GLint status = 0; 
    glGetProgramiv(skyProgram, GL_LINK_STATUS, &status); 
    if (!status) 
    { 
     std::cout << "failed to link" << std::endl; 
     GLchar log[256]; 
     GLsizei slen = 0; 
     glGetProgramInfoLog(skyProgram, 256, &slen, log); 
     std::cout << log << std::endl; 
    } 
    glDeleteShader(vertexShader); 
    glDeleteShader(fragmentShader); 
} 

然後在我的畫法,將裏面main方法被調用我這樣做:

glm::vec3 light_direction = glm::normalize(glm::vec3(1.f, 1.f, 3.f)); 
glm::vec3 light_position = glm::vec3(1.0f, 1.0f, 0.0f); 
glm::vec3 light_intensity = glm::vec3(1.f, 1.f, 1.f); 

glDepthMask(GL_FALSE); 
glUseProgram(skyProgram); 
glBindTexture(GL_TEXTURE_CUBE_MAP, textureCube); 
glUniform1i(glGetUniformLocation(skyProgram, "textureSampler"), 3); 
glUniform3fv(glGetUniformLocation(skyProgram, "light_direction"), 1, &light_direction[0]); 
glUniform3fv(glGetUniformLocation(skyProgram, "light_intensity"), 1, &light_intensity[0]); 
glUniform3fv(glGetUniformLocation(skyProgram, "view_position"), 1, &camera_position[0]); 
glUniform1f(glGetUniformLocation(skyProgram, "shininess"), 60); // shininess = 60, range is [0.0 - 128.0] 
glUniformMatrix3fv(glGetUniformLocation(skyProgram, "view_rot"), 1, GL_FALSE, &(glm::mat3(glm::inverse(view)))[0][0]); 

我看不到燈光立方體的面孔,我應該怎麼添加到我着色器?

+1

從我看來,你無處計算着色器中的任何照明。你肯定會得到OpenGL錯誤,因爲你正試圖設置着色器中不存在的制服。 – BDL

+1

@BDL:實際上,設置位置爲-1的制服顯然不會在GL中產生錯誤。 – derhass

回答

2

您發送光參數(light_directionlight_intensityview_positionshininess)進入着色器,但你不接受他們或做與他們任何事情。您的片段着色器只讀取紋理,但不適用任何照明到它:

outColor = texture(textureSampler, Coord); 

完整的源陰影將是大,沒有看到更多的代碼是很難給,所以我給一些指針:

  • 第一件事就是將一些glGetError()調用添加到C++代碼的各個部分,以便您知道是否使用OpenGL API錯誤。
  • 除了位置,你需要發送頂點法線到着色器
  • 你需要選擇一個着色算法,Blinn-Phong是簡單和廣泛使用。
  • 你需要確保正常的,光的方向是相同的座標空間

那麼,到底需要你outColor與計算出的陰影相乘:

outColor = texture(textureSampler, Coord) * shading; 

,但你需要修改你的頂點和片段着色器,根據光線的方向和頂點法線來計算它。

編輯基於GitHub project

我編譯並運行該項目,並必須解決一些問題:

  • 和庫路徑設定爲您的計算機,而不是相對於項目目錄。

  • 在片段着色器中,聲明「着色」爲「出」。刪除該行並添加vec4 shading = vec4(0.0, 0.0, 0.0, 1.0);shading += vec4...

  • vec4(light_intensity)是錯誤的,在我的NVIDIA的Windows驅動程序不能編譯,替換vec4(light_intensity,1.0)

我不能即使我修改了屏幕上得到什麼着色器始終輸出紅色。

+0

謝謝你的建議,我修改了代碼,但我真的很難理解/使陰影起作用。我在這裏上傳了我的整個代碼:https://github.com/luca92c/openGL。我不知道我從獲得簡單的Phong底紋效果到多遠,這是我的第一個OpenGL項目。 – splunk

+0

@splunk我馬上更新我的答案 – SurvivalMachine

+0

再次感謝您。現在我可以看到燈光效果。但是,你能解釋一下vec4中的4個參數(0.0,0.0,0.0,1.0)是什麼。意思? – splunk