void OGLShaderObject::_initActiveSubroutine() noexcept { #if !defined(EGLAPI) GLint numSubroutines = 0; GLint maxSubroutines = 0; glGetProgramStageiv(_program, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &numSubroutines); glGetProgramStageiv(_program, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_MAX_LENGTH, &maxSubroutines); if (numSubroutines) { auto nameSubroutines = make_scope<GLchar[]>(maxSubroutines + 1); nameSubroutines[maxSubroutines + 1] = 0; for (GLint i = 0; i < maxSubroutines; ++i) { GLenum type = GL_VERTEX_SHADER; glGetActiveSubroutineName(_program, type, i, maxSubroutines, 0, nameSubroutines.get()); GLint location = glGetSubroutineIndex(_program, type, nameSubroutines.get()); auto subroutines = std::make_shared<ShaderSubroutine>(); subroutines->setName(nameSubroutines.get()); subroutines->setLocation(location); _activeSubroutines.push_back(subroutines); } } #endif }
void GLshader::print_subroutines() { int maxSub,maxSubU,countActiveSU; char name[256]; int len, numCompS; GL_ASSERT(glGetIntegerv(GL_MAX_SUBROUTINES, &maxSub)); GL_ASSERT(glGetIntegerv(GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS, &maxSubU)); printf("Max Subroutines: %d Max Subroutine Uniforms: %d\n", maxSub,maxSubU); GL_ASSERT(glGetProgramStageiv(program, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &countActiveSU)); for (int i = 0; i < countActiveSU; ++i) { glGetActiveSubroutineUniformName(program, GL_VERTEX_SHADER, i, 256, &len, name); printf("Suroutine Uniform: %d name: %s\n", i,name); glGetActiveSubroutineUniformiv(program, GL_VERTEX_SHADER, i, GL_NUM_COMPATIBLE_SUBROUTINES, &numCompS); int *s = (int *) malloc(sizeof(int) * numCompS); glGetActiveSubroutineUniformiv(program, GL_VERTEX_SHADER, i, GL_COMPATIBLE_SUBROUTINES, s); printf("Compatible Subroutines:\n"); for (int j=0; j < numCompS; ++j) { glGetActiveSubroutineName(program, GL_VERTEX_SHADER, s[j], 256, &len, name); printf("\t%d - %s\n", s[j],name); } printf("\n"); free(s); } }
void GLProgram::getActiveSubroutineUniforms(std::vector<GLSLSubroutineUniform>& list, GLenum shaderType) const { GLint count; glGetProgramStageiv(_handle, shaderType, GL_ACTIVE_SUBROUTINE_UNIFORMS, &count); GLint biggerNameLength; glGetProgramStageiv(_handle, shaderType, GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH, &biggerNameLength); if (count != GL_INVALID_ENUM && biggerNameLength != GL_INVALID_ENUM) { list.reserve(count); GLchar* name = new GLchar[biggerNameLength]; for (GLuint index = 0; index < static_cast<GLuint>(count); ++index) { glGetActiveSubroutineUniformName(_handle, shaderType, index, biggerNameLength, 0, name); GLint location = glGetSubroutineUniformLocation(_handle, shaderType, name); GLint compatibleSubroutinesCount; glGetActiveSubroutineUniformiv(_handle, shaderType, index, GL_NUM_COMPATIBLE_SUBROUTINES, &compatibleSubroutinesCount); GLint* compatibleSubroutines = new GLint[compatibleSubroutinesCount]; glGetActiveSubroutineUniformiv(_handle, shaderType, index, GL_COMPATIBLE_SUBROUTINES, compatibleSubroutines); // @uniformArraySize is 1 if subroutine uniform is not an array GLint uniformArraySize; glGetActiveSubroutineUniformiv(_handle, shaderType, index, GL_UNIFORM_SIZE, &uniformArraySize); GLSLSubroutineUniform subroutineUniform; subroutineUniform.program = _handle; subroutineUniform.location = location; subroutineUniform.shaderType = shaderType; subroutineUniform.name = name; subroutineUniform.compatibleSubroutines = std::vector<GLint>(compatibleSubroutines, compatibleSubroutines + compatibleSubroutinesCount); subroutineUniform.uniformArraySize = uniformArraySize; list.push_back(subroutineUniform); delete[] compatibleSubroutines; } delete[] name; } }
void init(void) { glGenVertexArrays(1, &vao); glBindVertexArray(vao); GLfloat vertices[6][2] = { { -0.90, -0.90 }, // Triangle 1 { 0.85, -0.90 }, { -0.90, 0.85 }, { 0.90, -0.85 }, // Triangle 2 { 0.90, 0.90 }, { -0.85, 0.90 } }; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); h_prog = build_program_from_files("triangles.vert", "sel_func_subroutine_layout.frag"); glUseProgram(h_prog); loc_func = glGetSubroutineUniformLocation(h_prog, GL_FRAGMENT_SHADER, "func"); idx_shader_func[0] = 7; idx_shader_func[1] = 10; printf("location of the uniform subroutine \"func\" = %d\n", loc_func); glGetProgramStageiv(h_prog, GL_FRAGMENT_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_func); printf("# of active subroutine uniforms = %d\n", n_func); GLint n; glGetProgramStageiv(h_prog, GL_FRAGMENT_SHADER, GL_ACTIVE_SUBROUTINES, &n); printf("# of active subroutines = %d\n", n); char name[1024]; GLsizei length; glGetActiveSubroutineName(h_prog, GL_FRAGMENT_SHADER, idx_shader_func[0], 1024, &length, name); printf("subroutine name for index %d = %s\n", idx_shader_func[0], name); glGetActiveSubroutineName(h_prog, GL_FRAGMENT_SHADER, idx_shader_func[1], 1024, &length, name); printf("subroutine name for index %d = %s\n", idx_shader_func[1], name); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); glEnableVertexAttribArray(0); }
bool initProgram() { bool Validated = true; compiler Compiler; if(Validated) { GLuint VertShaderName = Compiler.create(GL_VERTEX_SHADER, getDataDirectory() + VERTEX_SHADER_SOURCE); GLuint FragShaderName = Compiler.create(GL_FRAGMENT_SHADER, getDataDirectory() + FRAGMENT_SHADER_SOURCE); ProgramName = glCreateProgram(); glAttachShader(ProgramName, VertShaderName); glAttachShader(ProgramName, FragShaderName); glLinkProgram(ProgramName); } if(Validated) { Validated = Validated && Compiler.check(); Validated = Validated && Compiler.check_program(ProgramName); } if(Validated) { GLint ProgramVertSubroutine(0); GLint ProgramFragSubroutine(0); glGetProgramStageiv(ProgramName, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &ProgramVertSubroutine); glGetProgramStageiv(ProgramName, GL_FRAGMENT_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &ProgramFragSubroutine); UniformMVP = glGetUniformLocation(ProgramName, "MVP"); UniformDXT1 = glGetUniformLocation(ProgramName, "DiffuseDXT1"); UniformRGB8 = glGetUniformLocation(ProgramName, "DiffuseRGB8"); UniformDisplacement = glGetUniformLocation(ProgramName, "Displacement"); UniformDiffuse = glGetSubroutineUniformLocation(ProgramName, GL_FRAGMENT_SHADER, "Diffuse"); IndexDXT1 = glGetSubroutineIndex(ProgramName, GL_FRAGMENT_SHADER, "diffuseLQ"); IndexRGB8 = glGetSubroutineIndex(ProgramName, GL_FRAGMENT_SHADER, "diffuseHQ"); } return Validated; }
void GLProgram::getActiveSubroutines(std::vector<std::string>& list, GLenum shaderType) const { GLint count; glGetProgramStageiv(_handle, shaderType, GL_ACTIVE_SUBROUTINES, &count); GLint biggerNameLength; glGetProgramStageiv(_handle, shaderType, GL_ACTIVE_SUBROUTINE_MAX_LENGTH, &biggerNameLength); if (count != GL_INVALID_ENUM && biggerNameLength != GL_INVALID_ENUM) { list.reserve(count); GLchar* name = new GLchar[biggerNameLength]; for (GLuint index = 0; index < static_cast<GLuint>(count); ++index) { glGetActiveSubroutineName(_handle, shaderType, index, biggerNameLength, 0, name); list.push_back(std::string(name)); } delete[] name; } }
void UniformGroup::apply_subroutines(ProgramPtr prog, GLenum shadertype, const std::unordered_map<std::string, std::string>& subroutines) { assert_gl("apply_subroutines:enter"); GLint num_uniform_locations; glGetProgramStageiv(prog->get_id(), shadertype, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, &num_uniform_locations); std::vector<GLuint> subroutine_mappings; for(int i = 0; i < num_uniform_locations; ++i) { char name[256]; GLsizei length; glGetActiveSubroutineUniformName(prog->get_id(), shadertype, i, sizeof(name), &length, name); const auto& it = subroutines.find(name); if (it == subroutines.end()) { log_error("unmapped subroutine: %s", name); } else { GLuint loc = glGetSubroutineIndex(prog->get_id(), shadertype, it->second.c_str()); if (loc == GL_INVALID_INDEX) { log_error("unknown subroutine: %s", it->second); } else { subroutine_mappings.emplace_back(loc); } } } glUniformSubroutinesuiv(shadertype, subroutine_mappings.size(), subroutine_mappings.data()); assert_gl("apply_subroutines:exit"); }
void Shader::addAllSubroutines() { GLenum interfaces[] = { GL_VERTEX_SUBROUTINE, GL_FRAGMENT_SUBROUTINE }; GLenum shader_stages[] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER }; GLint interfaces_count = sizeof(interfaces) / sizeof(interfaces[0]); for(GLint i = 0; i < interfaces_count; ++i) { /* Get all active subroutines */ GLenum program_interface = interfaces[i]; GLint num_subroutines = 0; glGetProgramInterfaceiv(m_program_id, program_interface, GL_ACTIVE_RESOURCES, &num_subroutines); const GLenum properties[] = { GL_NAME_LENGTH }; const GLint properties_size = sizeof(properties) / sizeof(properties[0]); GLint count_subroutine_locations = 0; glGetProgramStageiv(m_program_id, shader_stages[i], GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, &count_subroutine_locations); m_active_subroutine_uniform_locations[shader_stages[i]] = count_subroutine_locations; for (GLint j = 0; j < num_subroutines; ++j) { GLint values[properties_size]; GLint length = 0; glGetProgramResourceiv(m_program_id, program_interface, j, properties_size, properties, properties_size, &length, values); std::vector<char> name_data(values[0]); glGetProgramResourceName(m_program_id, program_interface, j, name_data.size(), nullptr, &name_data[0]); std::string subroutine_name(name_data.begin(), name_data.end() - 1); GLuint subroutine_index = glGetSubroutineIndex(m_program_id, shader_stages[i], subroutine_name.c_str()); m_subroutine_indices[subroutine_name] = subroutine_index; } } }
void ShaderEffect::SetSubroutineUniforms(uint_t shaderType, SubroutineLink* link, int numLinks) { int maxUniforms; glGetProgramStageiv(mProgram, shaderType, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, &maxUniforms); ASSERT(maxUniforms < MAX_SHADER_SUBROUTINES); for(int uniform = 0; uniform < maxUniforms; ++uniform) { if(uniform < numLinks) { SubroutineLink* ci = &link[uniform]; const int uniformIndex = glGetSubroutineUniformLocation(mProgram, shaderType, ci->UniformName); const int functionIndex = glGetSubroutineIndex(mProgram, shaderType, ci->FunctionName); mSubroutineMap[uniformIndex] = functionIndex; } } glUniformSubroutinesuiv(shaderType, maxUniforms, mSubroutineMap); }
void NGLScene::paintGL() { //---------------------------------------------------------------------------------------------------------------------- // draw to our FBO first //---------------------------------------------------------------------------------------------------------------------- // grab an instance of the shader manager ngl::ShaderLib *shader=ngl::ShaderLib::instance(); (*shader)["Phong"]->use(); glEnable(GL_MULTISAMPLE); // Rotation based on the mouse position for our global transform ngl::Mat4 rotX; ngl::Mat4 rotY; // create the rotation matrices rotX.rotateX(m_win.spinXFace); rotY.rotateY(m_win.spinYFace); // multiply the rotations m_mouseGlobalTX=rotY*rotX; // add the translations m_mouseGlobalTX.m_m[3][0] = m_modelPos.m_x; m_mouseGlobalTX.m_m[3][1] = m_modelPos.m_y; m_mouseGlobalTX.m_m[3][2] = m_modelPos.m_z; static float rot=0.0; // get the VBO instance and draw the built in teapot ngl::VAOPrimitives *prim=ngl::VAOPrimitives::instance(); // we are now going to draw to our FBO // set the rendering destination to FBO glBindFramebuffer(GL_FRAMEBUFFER, m_fboID); // set the background colour (using blue to show it up) glClearColor(0,0.4f,0.5f,1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // set our viewport to the size of the texture // if we want a different camera we wouldset this here glViewport(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT); // rotate the teapot m_transform.reset(); m_transform.setScale(1.8f,1.8f,1.8f); m_transform.setRotation(rot,rot,rot); loadMatricesToShader(); prim->draw("teapot"); rot+=0.1; //---------------------------------------------------------------------------------------------------------------------- // now we are going to draw to the normal GL buffer and use the texture created // in the previous render to draw to our objects //---------------------------------------------------------------------------------------------------------------------- // first bind the normal render buffer glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject()); // now enable the texture we just rendered to glDisable(GL_MULTISAMPLE); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_textureID); // set the screen for a different clear colour glClearColor(0.4f, 0.4f, 0.4f, 1.0f); // Grey Background // clear this screen glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // get the new shader and set the new viewport size shader->use("TextureShader"); GLsizei numActiveUniforms; glGetProgramStageiv(shader->getProgramID("TextureShader"), GL_FRAGMENT_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, &numActiveUniforms); glUniformSubroutinesuiv(GL_FRAGMENT_SHADER,numActiveUniforms,&m_subroutines[m_activeSubroutine]); // this takes into account retina displays etc glViewport(0, 0, static_cast<GLsizei>(width() * devicePixelRatio()), static_cast<GLsizei>(height() * devicePixelRatio())); ngl::Mat4 MVP; m_transform.reset(); MVP= m_project*m_view*m_mouseGlobalTX; shader->setUniform("MVP",MVP); prim->draw("plane"); m_transform.setPosition(0,1,0); MVP= m_project*m_view*m_mouseGlobalTX*m_transform.getMatrix(); shader->setUniform("MVP",MVP); prim->draw("sphere"); //---------------------------------------------------------------------------------------------------------------------- // glBindFramebuffer(GL_DRAW_FRAMEBUFFER, defaultFramebufferObject()); // Make sure no FBO is set as the draw framebuffer // glBindFramebuffer(GL_READ_FRAMEBUFFER, m_renderFBO); // Make sure your multisampled FBO is the read framebuffer // glDrawBuffer(GL_BACK); // Set the back buffer as the draw buffer // glBlitFramebuffer(0, 0, m_win.width, m_win.height, 0, 0, m_win.width, m_win.height, GL_COLOR_BUFFER_BIT, GL_NEAREST); }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GL40_nglGetProgramStageiv(JNIEnv *__env, jclass clazz, jint program, jint shadertype, jint pname, jlong valuesAddress, jlong __functionAddress) { GLint *values = (GLint *)(intptr_t)valuesAddress; glGetProgramStageivPROC glGetProgramStageiv = (glGetProgramStageivPROC)(intptr_t)__functionAddress; UNUSED_PARAMS(__env, clazz) glGetProgramStageiv(program, shadertype, pname, values); }