opengl
Shader लोड हो रहा है और संकलन
खोज…
परिचय
ये उदाहरण शेड्स को लोड करने और संकलित करने के विभिन्न तरीकों को प्रदर्शित करते हैं। सभी उदाहरणों में त्रुटि हैंडलिंग कोड शामिल होना चाहिए ।
टिप्पणियों
Shader ऑब्जेक्ट, जैसा कि glCreateShader
से बनाया गया है, बहुत कुछ नहीं करता है। इनमें एकल चरण के लिए संकलित कोड होता है, लेकिन उन्हें उस चरण के लिए पूरा संकलित कोड समाहित करने की आवश्यकता नहीं होती है। कई मायनों में, वे सी और सी ++ ऑब्जेक्ट फ़ाइलों की तरह काम करते हैं।
प्रोग्राम ऑब्जेक्ट्स में अंतिम लिंक्ड प्रोग्राम होता है। लेकिन वे कार्यक्रम के समान मूल्यों के लिए राज्य के साथ-साथ कई अन्य राज्य डेटा भी रखते हैं। उनके पास shader के इंटरफ़ेस डेटा को इंट्रोस्पेक्ट करने के लिए API हैं (हालांकि यह केवल GL 4.3 में व्यापक हो गया है)। प्रोग्राम ऑब्जेक्ट्स वह हैं जो उस shader कोड को परिभाषित करता है जिसे आप रेंडर करते समय उपयोग करते हैं।
एक बार किसी प्रोग्राम को लिंक करने के लिए उपयोग किए जाने वाले शेड ऑब्जेक्ट्स की अब आवश्यकता नहीं है, जब तक आप अन्य प्रोग्रामों को लिंक करने के लिए उनका उपयोग करने का इरादा नहीं रखते हैं।
सी ++ में अलग होने योग्य लोड करें
यह कोड एक एकल फ़ाइल को लोड, संकलित और लिंक करता है, जो एकल चरण के लिए एक अलग shader प्रोग्राम बनाता है। यदि त्रुटियाँ हैं, तो यह उन त्रुटियों के लिए जानकारी-लॉग प्राप्त करेगा।
कोड कुछ सामान्यतः उपलब्ध C ++ 11 कार्यक्षमता का उपयोग करता है।
#include <string>
#include <fstream>
//In C++17, we could take a `std::filesystem::path` instead of a std::string
//for the filename.
GLuint CreateSeparateProgram(GLenum stage, const std::string &filename)
{
std::ifstream input(filename.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
//Figure out how big the file is.
auto fileSize = input.tellg();
input.seekg(0, ios::beg);
//Read the whole file.
std::string fileData(fileSize);
input.read(&fileData[0], fileSize);
input.close();
//Compile&link the file
auto fileCstr = (const GLchar *)fileData.c_str();
auto program = glCreateShaderProgramv(stage, 1, &fileCstr);
//Check for errors
GLint isLinked = 0;
glGetProgramiv(program, GL_LINK_STATUS, &isLinked);
if(isLinked == GL_FALSE)
{
//Note: maxLength includes the NUL terminator.
GLint maxLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
//C++11 does not permit you to overwrite the NUL terminator,
//even if you are overwriting it with the NUL terminator.
//C++17 does, so you could subtract 1 from the length and skip the `pop_back`.
std::basic_string<GLchar> infoLog(maxLength);
glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
infoLog.pop_back();
//The program is useless now. So delete it.
glDeleteProgram(program);
//Use the infoLog in whatever manner you deem best.
//Exit with failure.
return 0;
}
return program;
}
C ++ में व्यक्तिगत शेडर ऑब्जेक्ट संकलन
पारंपरिक GLSL संकलन मॉडल में एक shader चरण के लिए एक shader ऑब्जेक्ट में संकलन कोड शामिल होता है, फिर एक ही प्रोग्राम ऑब्जेक्ट में कई shader ऑब्जेक्ट्स को जोड़ना (उन सभी चरणों को कवर करना चाहता है)।
4.2 के बाद से, प्रोग्राम ऑब्जेक्ट्स बनाए जा सकते हैं जिनमें केवल एक shader स्टेज होता है। यह विधि सभी शेडर चरणों को एक कार्यक्रम में जोड़ती है।
शेडर ऑब्जेक्ट संकलन
#include <string>
#include <fstream>
//In C++17, we could take a `std::filesystem::path` instead of a std::string
//for the filename.
GLuint CreateShaderObject(GLenum stage, const std::string &filename)
{
std::ifstream input(filename.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
//Figure out how big the file is.
auto fileSize = input.tellg();
input.seekg(0, ios::beg);
//Read the whole file.
std::string fileData(fileSize);
input.read(&fileData[0], fileSize);
input.close();
//Create a shader name
auto shader = glCreateShader(stage);
//Send the shader source code to GL
auto fileCstr = (const GLchar *)fileData.c_str();
glShaderSource(shader, 1, &fileCstr, nullptr);
//Compile the shader
glCompileShader(shader);
GLint isCompiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
if(isCompiled == GL_FALSE)
{
GLint maxLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
//C++11 does not permit you to overwrite the NUL terminator,
//even if you are overwriting it with the NUL terminator.
//C++17 does, so you could subtract 1 from the length and skip the `pop_back`.
std::basic_string<GLchar> infoLog(maxLength);
glGetShaderInfoLog(shader, maxLength, &maxLength, &infoLog[0]);
infoLog.pop_back();
//We don't need the shader anymore.
glDeleteShader(shader);
//Use the infoLog as you see fit.
//Exit with failure.
return 0;
}
return shader;
}
प्रोग्राम ऑब्जेक्ट लिंकिंग
#include <string>
GLuint LinkProgramObject(vector<GLuint> shaders)
{
//Get a program object.
auto program = glCreateProgram();
//Attach our shaders to our program
for(auto shader : shaders)
glAttachShader(program, shader);
//Link our program
glLinkProgram(program);
//Note the different functions here: glGetProgram* instead of glGetShader*.
GLint isLinked = 0;
glGetProgramiv(program, GL_LINK_STATUS, (int *)&isLinked);
if(isLinked == GL_FALSE)
{
GLint maxLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
//C++11 does not permit you to overwrite the NUL terminator,
//even if you are overwriting it with the NUL terminator.
//C++17 does, so you could subtract 1 from the length and skip the `pop_back`.
std::basic_string<GLchar> infoLog(maxLength);
glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
infoLog.pop_back();
//We don't need the program anymore.
glDeleteProgram(program);
//Use the infoLog as you see fit.
//Exit with failure
return 0;
}
//Always detach shaders after a successful link.
for(auto shader : shaders)
gldetachShader(program, shader);
return program;
}